techprotrade's picture
download
raw
8.68 kB
# 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.