Buckets:
| # reference: https://github.com/shibukawa/imagesize_py | |
| import io | |
| import os | |
| import re | |
| import struct | |
| def _convertToPx(value): | |
| matched = re.match(r"(\d+(?:\.\d+)?)?([a-z]*)$", value) | |
| if not matched: | |
| raise ValueError("unknown length value: %s" % value) | |
| length, unit = matched.groups() | |
| if unit == "": | |
| return float(length) | |
| elif unit == "cm": | |
| return float(length) * 96 / 2.54 | |
| elif unit == "mm": | |
| return float(length) * 96 / 2.54 / 10 | |
| elif unit == "in": | |
| return float(length) * 96 | |
| elif unit == "pc": | |
| return float(length) * 96 / 6 | |
| elif unit == "pt": | |
| return float(length) * 96 / 6 | |
| elif unit == "px": | |
| return float(length) | |
| raise ValueError("unknown unit type: %s" % unit) | |
| def get(filepath): | |
| """ | |
| Return (width, height) for a given img file content | |
| no requirements | |
| :type filepath: Union[bytes, str, pathlib.Path] | |
| :rtype Tuple[int, int] | |
| """ | |
| height = -1 | |
| width = -1 | |
| if isinstance(filepath, io.BytesIO): # file-like object | |
| fhandle = filepath | |
| else: | |
| fhandle = open(filepath, 'rb') | |
| try: | |
| head = fhandle.read(31) | |
| size = len(head) | |
| # handle GIFs | |
| if size >= 10 and head[:6] in (b'GIF87a', b'GIF89a'): | |
| # Check to see if content_type is correct | |
| try: | |
| width, height = struct.unpack("<hh", head[6:10]) | |
| except struct.error: | |
| raise ValueError("Invalid GIF file") | |
| # see png edition spec bytes are below chunk length then and finally the | |
| elif size >= 24 and head.startswith(b'\211PNG\r\n\032\n') and head[12:16] == b'IHDR': | |
| try: | |
| width, height = struct.unpack(">LL", head[16:24]) | |
| except struct.error: | |
| raise ValueError("Invalid PNG file") | |
| # Maybe this is for an older PNG version. | |
| elif size >= 16 and head.startswith(b'\211PNG\r\n\032\n'): | |
| # Check to see if we have the right content type | |
| try: | |
| width, height = struct.unpack(">LL", head[8:16]) | |
| except struct.error: | |
| raise ValueError("Invalid PNG file") | |
| # handle JPEGs | |
| elif size >= 2 and head.startswith(b'\377\330'): | |
| try: | |
| fhandle.seek(0) # Read 0xff next | |
| size = 2 | |
| ftype = 0 | |
| while not 0xc0 <= ftype <= 0xcf or ftype in [0xc4, 0xc8, 0xcc]: | |
| fhandle.seek(size, 1) | |
| byte = fhandle.read(1) | |
| while ord(byte) == 0xff: | |
| byte = fhandle.read(1) | |
| ftype = ord(byte) | |
| size = struct.unpack('>H', fhandle.read(2))[0] - 2 | |
| # We are at a SOFn block | |
| fhandle.seek(1, 1) # Skip `precision' byte. | |
| height, width = struct.unpack('>HH', fhandle.read(4)) | |
| except (struct.error, TypeError): | |
| raise ValueError("Invalid JPEG file") | |
| # handle JPEG2000s | |
| elif size >= 12 and head.startswith(b'\x00\x00\x00\x0cjP \r\n\x87\n'): | |
| fhandle.seek(48) | |
| try: | |
| height, width = struct.unpack('>LL', fhandle.read(8)) | |
| except struct.error: | |
| raise ValueError("Invalid JPEG2000 file") | |
| # handle big endian TIFF | |
| elif size >= 8 and head.startswith(b"\x4d\x4d\x00\x2a"): | |
| offset = struct.unpack('>L', head[4:8])[0] | |
| fhandle.seek(offset) | |
| ifdsize = struct.unpack(">H", fhandle.read(2))[0] | |
| for i in range(ifdsize): | |
| tag, datatype, count, data = struct.unpack(">HHLL", fhandle.read(12)) | |
| if tag == 256: | |
| if datatype == 3: | |
| width = int(data / 65536) | |
| elif datatype == 4: | |
| width = data | |
| else: | |
| raise ValueError("Invalid TIFF file: width column data type should be SHORT/LONG.") | |
| elif tag == 257: | |
| if datatype == 3: | |
| height = int(data / 65536) | |
| elif datatype == 4: | |
| height = data | |
| else: | |
| raise ValueError("Invalid TIFF file: height column data type should be SHORT/LONG.") | |
| if width != -1 and height != -1: | |
| break | |
| if width == -1 or height == -1: | |
| raise ValueError("Invalid TIFF file: width and/or height IDS entries are missing.") | |
| elif size >= 8 and head.startswith(b"\x49\x49\x2a\x00"): | |
| offset = struct.unpack('<L', head[4:8])[0] | |
| fhandle.seek(offset) | |
| ifdsize = struct.unpack("<H", fhandle.read(2))[0] | |
| for i in range(ifdsize): | |
| tag, datatype, count, data = struct.unpack("<HHLL", fhandle.read(12)) | |
| if tag == 256: | |
| width = data | |
| elif tag == 257: | |
| height = data | |
| if width != -1 and height != -1: | |
| break | |
| if width == -1 or height == -1: | |
| raise ValueError("Invalid TIFF file: width and/or height IDS entries are missing.") | |
| # handle little endian BigTiff | |
| elif size >= 8 and head.startswith(b"\x49\x49\x2b\x00"): | |
| bytesize_offset = struct.unpack('<L', head[4:8])[0] | |
| if bytesize_offset != 8: | |
| raise ValueError('Invalid BigTIFF file: Expected offset to be 8, found {} instead.'.format(offset)) | |
| offset = struct.unpack('<Q', head[8:16])[0] | |
| fhandle.seek(offset) | |
| ifdsize = struct.unpack("<Q", fhandle.read(8))[0] | |
| for i in range(ifdsize): | |
| tag, datatype, count, data = struct.unpack("<HHQQ", fhandle.read(20)) | |
| if tag == 256: | |
| width = data | |
| elif tag == 257: | |
| height = data | |
| if width != -1 and height != -1: | |
| break | |
| if width == -1 or height == -1: | |
| raise ValueError("Invalid BigTIFF file: width and/or height IDS entries are missing.") | |
| # handle SVGs | |
| elif size >= 5 and (head.startswith(b'<?xml') or head.startswith(b'<svg')): | |
| fhandle.seek(0) | |
| data = fhandle.read(1024) | |
| try: | |
| data = data.decode('utf-8') | |
| width = re.search(r'[^-]width="(.*?)"', data).group(1) | |
| height = re.search(r'[^-]height="(.*?)"', data).group(1) | |
| except Exception: | |
| raise ValueError("Invalid SVG file") | |
| width = _convertToPx(width) | |
| height = _convertToPx(height) | |
| # handle Netpbm | |
| elif head[:1] == b"P" and head[1:2] in b"123456": | |
| fhandle.seek(2) | |
| sizes = [] | |
| while True: | |
| next_chr = fhandle.read(1) | |
| if next_chr.isspace(): | |
| continue | |
| if next_chr == b"": | |
| raise ValueError("Invalid Netpbm file") | |
| if next_chr == b"#": | |
| fhandle.readline() | |
| continue | |
| if not next_chr.isdigit(): | |
| raise ValueError("Invalid character found on Netpbm file") | |
| size = next_chr | |
| next_chr = fhandle.read(1) | |
| while next_chr.isdigit(): | |
| size += next_chr | |
| next_chr = fhandle.read(1) | |
| sizes.append(int(size)) | |
| if len(sizes) == 2: | |
| break | |
| fhandle.seek(-1, os.SEEK_CUR) | |
| width, height = sizes | |
| elif head.startswith(b"RIFF") and head[8:12] == b"WEBP": | |
| if head[12:16] == b"VP8 ": | |
| width, height = struct.unpack("<HH", head[26:30]) | |
| elif head[12:16] == b"VP8X": | |
| width = struct.unpack("<I", head[24:27] + b"\0")[0] | |
| height = struct.unpack("<I", head[27:30] + b"\0")[0] | |
| elif head[12:16] == b"VP8L": | |
| b = head[21:25] | |
| width = (((b[1] & 63) << 8) | b[0]) + 1 | |
| height = (((b[3] & 15) << 10) | (b[2] << 2) | ((b[1] & 192) >> 6)) + 1 | |
| else: | |
| raise ValueError("Unsupported WebP file") | |
| finally: | |
| fhandle.close() | |
| return width, height |
Xet Storage Details
- Size:
- 8.68 kB
- Xet hash:
- 54dfb734fc3218aef0ae06dc05838d633b55f1217b79bfab5087016e6d5a7e82
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.