Return the (width, height) of an image, given an open file or a path. Set 'close' to True to close the file at the end if it is initially in an open state.
(file_or_path, close=False)
| 33 | |
| 34 | |
| 35 | def get_image_dimensions(file_or_path, close=False): |
| 36 | """ |
| 37 | Return the (width, height) of an image, given an open file or a path. Set |
| 38 | 'close' to True to close the file at the end if it is initially in an open |
| 39 | state. |
| 40 | """ |
| 41 | from PIL import ImageFile as PillowImageFile |
| 42 | |
| 43 | p = PillowImageFile.Parser() |
| 44 | if hasattr(file_or_path, "read"): |
| 45 | file = file_or_path |
| 46 | file_pos = file.tell() |
| 47 | file.seek(0) |
| 48 | else: |
| 49 | try: |
| 50 | file = open(file_or_path, "rb") |
| 51 | except OSError: |
| 52 | return (None, None) |
| 53 | close = True |
| 54 | try: |
| 55 | # Most of the time Pillow only needs a small chunk to parse the image |
| 56 | # and get the dimensions, but with some TIFF files Pillow needs to |
| 57 | # parse the whole file. |
| 58 | chunk_size = 1024 |
| 59 | while 1: |
| 60 | data = file.read(chunk_size) |
| 61 | if not data: |
| 62 | break |
| 63 | try: |
| 64 | p.feed(data) |
| 65 | except zlib.error as e: |
| 66 | # ignore zlib complaining on truncated stream, just feed more |
| 67 | # data to parser (ticket #19457). |
| 68 | if e.args[0].startswith("Error -5"): |
| 69 | pass |
| 70 | else: |
| 71 | raise |
| 72 | except struct.error: |
| 73 | # Ignore PIL failing on a too short buffer when reads return |
| 74 | # less bytes than expected. Skip and feed more data to the |
| 75 | # parser (ticket #24544). |
| 76 | pass |
| 77 | except RuntimeError: |
| 78 | # e.g. "RuntimeError: could not create decoder object" for |
| 79 | # WebP files. A different chunk_size may work. |
| 80 | pass |
| 81 | if p.image: |
| 82 | return p.image.size |
| 83 | chunk_size *= 2 |
| 84 | return (None, None) |
| 85 | finally: |
| 86 | if close: |
| 87 | file.close() |
| 88 | else: |
| 89 | file.seek(file_pos) |