Viewing file: imagesize.py (5.73 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# -*- coding: utf-8 -*- # # (c) Copyright 2001-2006 Hewlett-Packard Development Company, L.P. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Don Welch
# # Ported from Perl's Image::Size module by Randy J. Ray #
import os, os.path, re, struct
xbm_pat = re.compile(r'^\#define\s*\S*\s*(\d+)\s*\n\#define\s*\S*\s*(\d+)', re.IGNORECASE) xpm_pat = re.compile(r'"\s*(\d+)\s+(\d+)(\s+\d+\s+\d+){1,2}\s*"', re.IGNORECASE) ppm_pat1 = re.compile(r'^\#.*', re.IGNORECASE | re.MULTILINE) ppm_pat2 = re.compile(r'^(P[1-6])\s+(\d+)\s+(\d+)', re.IGNORECASE) ppm_pat3 = re.compile(r'IMGINFO:(\d+)x(\d+)', re.IGNORECASE) tiff_endian_pat = re.compile(r'II\x2a\x00')
def readin(stream, length, offset=0): if offset != 0: stream.seek(offset, 0)
return stream.read(length)
def xbmsize(stream): width, height = -1, -1 match = xbm_pat.match(readin(stream,1024))
try: width = int(match.group(1)) height = int(match.group(2)) except: pass
return width, height
def xpmsize(stream): width, height = -1, -1 match = re.search(xpm_pat, readin(stream, 1024)) try: width = int(match.group(1)) height = int(match.group(2)) except: pass
return width, height
def pngsize(stream): # also does MNG width, height = -1, -1
if readin(stream, 4, 12) in ('IHDR', 'MHDR'): height, width = struct.unpack("!II", stream.read(8))
return width,height
def jpegsize(stream): width, height = -1, -1 stream.seek(2) while True: length = 4 buffer = readin(stream, length) try: marker, code, length = struct.unpack("!c c h", buffer) except: break
if marker != '\xff': break
if 0xc0 <= ord(code) <= 0xc3: length = 5 height, width = struct.unpack("!xhh", readin(stream, length))
else: readin(stream, length-2)
return width, height
def ppmsize(stream): width, height = -1, -1 header = re.sub(ppm_pat1, '', readin(stream, 1024)) match = ppm_pat2.match(header) typ = '' try: typ = match.group(1) width = int(match.group(2)) height = int(match.group(3)) except: pass
if typ == 'P7': match = ppm_pat3.match(header)
try: width = int(match.group(1)) height = int(match.group(2)) except: pass
return width, height
def tiffsize(stream): header = readin(stream, 4) endian = ">" match = tiff_endian_pat.match(header)
if match is not None: endian = "<"
input = readin(stream, 4, 4) offset = struct.unpack('%si' % endian, input)[0] num_dirent = struct.unpack('%sH' % endian, readin(stream, 2, offset))[0] offset += 2 num_dirent = offset+(num_dirent*12) width, height = -1, -1
while True: ifd = readin(stream, 12, offset)
if ifd == '' or offset > num_dirent: break
offset += 12 tag = struct.unpack('%sH'% endian, ifd[0:2])[0] type = struct.unpack('%sH' % endian, ifd[2:4])[0]
if tag == 0x0100: width = struct.unpack("%si" % endian, ifd[8:12])[0]
elif tag == 0x0101: height = struct.unpack("%si" % endian, ifd[8:12])[0]
return width, height
def bmpsize(stream): width, height = struct.unpack("<II", readin(stream, 8, 18)) return width, height
def gifsize(stream): # since we only care about the printed size of the image # we only need to get the logical screen sizes, which are # the maximum extents of the image. This code is much simpler # than the code from Image::Size #width, height = -1, -1 buf = readin(stream, 7, 6) # LSx, GCTF, etc height, width, flags, bci, par = struct.unpack('<HHBBB', buf)
return width, height
TYPE_MAP = {re.compile('^GIF8[7,9]a') : ('image/gif', gifsize), re.compile("^\xFF\xD8") : ('image/jpeg', jpegsize), re.compile("^\x89PNG\x0d\x0a\x1a\x0a") : ('image/png', pngsize), re.compile("^P[1-7]") : ('image/x-portable-pixmap', ppmsize), re.compile('\#define\s+\S+\s+\d+') : ('image/x-xbitmap', xbmsize), re.compile('\/\* XPM \*\/') : ('image/x-xpixmap', xpmsize), re.compile('^MM\x00\x2a') : ('image/tiff', tiffsize), re.compile('^II\*\x00') : ('image/tiff', tiffsize), re.compile('^BM') : ('image/x-bitmap', bmpsize), re.compile("^\x8aMNG\x0d\x0a\x1a\x0a") : ('image/png', pngsize), }
def imagesize(filename, mime_type=''): width, height = -1, -1
f = file(filename, 'r') buffer = f.read(4096)
if not mime_type: for t in TYPE_MAP: match = t.search(buffer) if match is not None: mime_type, func = TYPE_MAP[t] break
if mime_type and func: f.seek(0) width, height = func(f) else: width, height = -1, -1
f.close()
return height, width, mime_type
|