Last active
January 12, 2021 09:52
-
-
Save EdgeCaseBerg/8240859 to your computer and use it in GitHub Desktop.
Python function to read out size data for image types with no dependencies.
Found originally at http://stackoverflow.com/questions/15800704/python-get-image-size-without-loading-image-into-memory and I added the ICO handler. (just ico not cursor files)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#------------------------------------------------------------------------------- | |
# Name: get_image_size | |
# Purpose: extract image dimensions given a file path using just | |
# core modules | |
# | |
# Author: Paulo Scardine (based on code from Emmanuel VAÏSSE), Ethan Eldridge (ICO) | |
# | |
# Created: 26/09/2013 | |
# Copyright: (c) Paulo Scardine 2013 | |
# Licence: MIT | |
#------------------------------------------------------------------------------- | |
#!/usr/bin/env python | |
import os | |
import struct | |
class UnknownImageFormat(Exception): | |
pass | |
def get_image_size(file_path): | |
""" | |
Return (width, height) for a given img file content - no external | |
dependencies except the os and struct modules from core | |
""" | |
size = os.path.getsize(file_path) | |
with open(file_path) as input: | |
height = -1 | |
width = -1 | |
data = input.read(25) | |
if (size >= 10) and data[:6] in ('GIF87a', 'GIF89a'): | |
# GIFs | |
w, h = struct.unpack("<HH", data[6:10]) | |
width = int(w) | |
height = int(h) | |
elif ((size >= 24) and data.startswith('\211PNG\r\n\032\n') | |
and (data[12:16] == 'IHDR')): | |
# PNGs | |
w, h = struct.unpack(">LL", data[16:24]) | |
width = int(w) | |
height = int(h) | |
elif (size >= 16) and data.startswith('\211PNG\r\n\032\n'): | |
# older PNGs? | |
w, h = struct.unpack(">LL", data[8:16]) | |
width = int(w) | |
height = int(h) | |
elif (size >= 2) and data.startswith('\377\330'): | |
# JPEG | |
msg = " raised while trying to decode as JPEG." | |
input.seek(0) | |
input.read(2) | |
b = input.read(1) | |
try: | |
while (b and ord(b) != 0xDA): | |
while (ord(b) != 0xFF): b = input.read(1) | |
while (ord(b) == 0xFF): b = input.read(1) | |
if (ord(b) >= 0xC0 and ord(b) <= 0xC3): | |
input.read(3) | |
h, w = struct.unpack(">HH", input.read(4)) | |
break | |
else: | |
input.read(int(struct.unpack(">H", input.read(2))[0])-2) | |
b = input.read(1) | |
width = int(w) | |
height = int(h) | |
except struct.error: | |
raise UnknownImageFormat("StructError" + msg) | |
except ValueError: | |
raise UnknownImageFormat("ValueError" + msg) | |
except Exception as e: | |
raise UnknownImageFormat(e.__class__.__name__ + msg) | |
elif (file_path.endswith('.ico')): | |
#see http://en.wikipedia.org/wiki/ICO_(file_format) | |
input.seek(0) | |
reserved = input.read(2) | |
if 0 != struct.unpack("<H", reserved )[0]: | |
raise UnknownImageFormat("Corrupt ICON File") | |
format = input.read(2) | |
assert 1 == struct.unpack("<H", format)[0] | |
num = input.read(2) | |
num = struct.unpack("<H", num)[0] | |
if num > 1: | |
import warnings | |
warnings.warn("ICO File contains more than one image") | |
#http://msdn.microsoft.com/en-us/library/ms997538.aspx | |
w = input.read(1) | |
h = input.read(1) | |
width = ord(w) | |
height = ord(h) | |
else: | |
raise UnknownImageFormat( | |
"Sorry, don't know how to get information from %s." % file_path | |
) | |
return width, height |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's a version (not tested for ICO!) that gets the number of channels as well (at some point, someone else will also add in things to return the bit depth, I guess):