"""Multimedia helpers for images, etc."""
import logging
import os
import struct
import sys
__all__ = ["choose_height", "get_dimensions_pil", "get_dimensions"]
def choose_height(new_width, width, height):
"""Return the height corresponding to ``new_width`` that's proportional
to the original size (``width`` x ``height``).
"""
proportion = float(height) / float(width)
return int(new_width * proportion)
def get_dimensions_pil(path, default=(None, None)):
"""Get an image's size using the Python Imaging Library (PIL)
Returns ``(width, height)`` as two integers, or ``default`` if the size
could not be ascertained. Failuer usually means the file does not exist
or is not in a format recognized by PIL.
Depends on the Python Imaging Library (http://pypi.python.org/pypi/PIL).
See ``get_dimensions()`` if your application is not otherwise using PIL.
"""
import Image
try:
im = Image(path)
except Exception:
return default
return im.size
def get_dimensions(path, default=(None, None)):
"""Get an image's size using only the Python standard library
Returns ``(width, height)`` as two integers, or ``default`` if the size
could not be ascertained. Failure usually means the file does not exist
or is not in a recognized format. Only JPG/PNG/GIF/BMP are supported at
this time.
The algorithms are based on a PyCode recipe by Perenzo/Welch/Ray.
(http://www.pycode.com/modules/?id=32&tab=download)
This helper recognizes fewer image formats and is potentially less
accurate than ``get_dimensions_pil()``.
"""
apath = os.path.abspath(path)
try:
f = open(path, "rb")
except IOError:
return default
try:
header = f.read(1024)
# JPG
if header.startswith("\xFF\xD8"):
width = height = None
f.seek(2)
while True:
length = 4
buf = f.read(length)
try:
marker, code, length = struct.unpack("!ccH", buf)
except Exception:
break
if marker != "\xff":
break
if 0xc0 <= ord(code) <= 0xc3:
length = 5
buf = f.read(length)
height, width = struct.unpack("!xHH", buf)
else:
f.read(length-2)
return width, height
# PNG
elif header.startswith("\x89PNG\x0d\x0a\x1a\x0a") or \
header.startswith("\x8aMNG\x0d\x0a\x1a\x0a"):
f.seek(12)
control = f.read(4)
if control in ["IHDR", "MHDR"]:
buf = f.read(8)
width, height = struct.unpack("!II", buf)
return width, height
# GIF
elif header.startswith("GIF87a") or header.startswith("GIF89a"):
f.seek(6)
buf = f.read(7)
width, height, flags, bci, par = struct.unpack("