source: trunk/src/testing/ui/misc/imsize.py @ 4

Revision 4, 6.0 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2# (c) Copyright 2001-2005 Hewlett-Packard Development Company, L.P.
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17#
18# Author: Don Welch
19# Ported from Perl's Image::Size module by Randy J. Ray
20# Modified by Perenzo, 2006
21
22import os, os.path, re, struct
23
24xbm_pat = re.compile(r'^\#define\s*\S*\s*(\d+)\s*\n\#define\s*\S*\s*(\d+)', re.IGNORECASE)
25xpm_pat = re.compile(r'"\s*(\d+)\s+(\d+)(\s+\d+\s+\d+){1,2}\s*"', re.IGNORECASE)
26ppm_pat1 = re.compile(r'^\#.*', re.IGNORECASE | re.MULTILINE)
27ppm_pat2 = re.compile(r'^(P[1-6])\s+(\d+)\s+(\d+)', re.IGNORECASE)
28ppm_pat3 = re.compile(r'IMGINFO:(\d+)x(\d+)', re.IGNORECASE)
29tiff_endian_pat = re.compile(r'II\x2a\x00')
30
31def readin(stream, length, offset=0):
32    if offset != 0:
33        stream.seek(offset, 0)
34    return stream.read(length)
35
36def xbmsize(stream):
37    width, height = -1, -1
38    match = xbm_pat.match(readin(stream, 1024))
39    try:
40        width = int(match.group(1))
41        height = int(match.group(2))
42    except:
43        pass
44    return width, height
45
46def xpmsize(stream):
47    width, height = -1, -1
48    match = re.search(xpm_pat, readin(stream, 1024))
49    try:
50        width = int(match.group(1))
51        height = int(match.group(2))
52    except:
53        pass
54    return width, height
55
56def pngsize(stream): # also does MNG
57    width, height = -1, -1
58    if readin(stream, 4, 12) in ('IHDR', 'MHDR'):
59        height, width = struct.unpack("!II", stream.read(8))
60
61    return height, width #width, height
62
63def jpegsize(stream):
64    width, height = -1, -1
65    stream.seek(2)
66    while 1:
67        length = 4
68        buffer = readin(stream, length)
69        try:
70            marker, code, length = struct.unpack("!ccH", buffer)
71        except:
72            break
73        if marker != '\xff':
74            break
75        if 0xc0 <= ord(code) <= 0xc3:
76            length = 5
77            height, width = struct.unpack("!xHH", readin(stream, length))
78        else:
79            readin(stream, length-2)
80    return width, height
81
82def ppmsize(stream):
83    width, height = -1, -1
84    header = re.sub(ppm_pat1, '', readin(stream, 1024))
85    match = ppm_pat2.match(header)
86    typ = ''
87    try:
88        typ = match.group(1)
89        width = int(match.group(2))
90        height = int(match.group(3))
91    except:
92        pass
93    if typ == 'P7':
94        match = ppm_pat3.match(header)
95
96        try:
97            width = int(match.group(1))
98            height = int(match.group(2))
99        except:
100            pass
101    return width, height
102
103def tiffsize(stream):
104    header = readin(stream, 4)
105    endian = ">"
106    match = tiff_endian_pat.match(header)
107    if match is not None:
108        endian = "<"
109    input = readin(stream, 4, 4)
110    offset = struct.unpack('%si' % endian, input)[0]
111    num_dirent = struct.unpack('%sH' % endian, readin(stream, 2, offset))[0]
112    offset += 2
113    num_dirent = offset+(num_dirent*12)
114    width, height = -1, -1
115    while True:
116        ifd = readin(stream, 12, offset)
117        if ifd == '' or offset > num_dirent:
118            break
119        offset += 12
120        tag = struct.unpack('%sH'% endian, ifd[0:2])[0]
121        type = struct.unpack('%sH' % endian, ifd[2:4])[0]
122        if tag == 0x0100:
123            width = struct.unpack("%si" % endian, ifd[8:12])[0]
124        elif tag == 0x0101:
125            height = struct.unpack("%si" % endian, ifd[8:12])[0]
126    return width, height
127
128def bmpsize(stream):
129    width, height = struct.unpack("<II", readin(stream, 8, 18))
130    return width, height
131
132def gifsize(stream):
133    # since we only care about the printed size of the image
134    # we only need to get the logical screen sizes, which are
135    # the maximum extents of the image. This code is much simpler
136    # than the code from Image::Size
137    #width, height = -1, -1
138    buf = readin(stream, 7, 6) # LSx, GCTF, etc
139    height, width, flags, bci, par = struct.unpack('<HHBBB', buf)
140    return height, width #width, height
141
142TYPE_MAP = { re.compile('^GIF8[7,9]a')              : ('image/gif', gifsize),
143             re.compile("^\xFF\xD8")                : ('image/jpeg', jpegsize),
144             re.compile("^\x89PNG\x0d\x0a\x1a\x0a") : ('image/png', pngsize),
145             re.compile("^P[1-7]")                  : ('image/x-portable-pixmap', ppmsize),
146             re.compile('\#define\s+\S+\s+\d+')     : ('image/x-xbitmap', xbmsize),
147             re.compile('\/\* XPM \*\/')            : ('image/x-xpixmap', xpmsize),
148             re.compile('^MM\x00\x2a')              : ('image/tiff', tiffsize),
149             re.compile('^II\*\x00')                : ('image/tiff', tiffsize),
150             re.compile('^BM')                      : ('image/x-bitmap', bmpsize),
151             re.compile("^\x8aMNG\x0d\x0a\x1a\x0a") : ('image/png', pngsize),
152           }
153
154def imagesize(filename, mime_type=''):
155    width, height = -1, -1
156    f = file(filename, 'rb')
157    buffer = f.read(4096)
158    if not mime_type:
159        for t in TYPE_MAP:
160            match = t.search(buffer)
161            if match is not None:
162                mime_type, func = TYPE_MAP[t]
163                break
164    if mime_type and func:
165        f.seek(0)
166        width, height = func(f)
167    else:
168        width, height = -1, -1
169    f.close()
170    return height, width, mime_type
171
172if __name__=="__main__":
173    import sys
174    print imagesize(sys.argv[1])
Note: See TracBrowser for help on using the repository browser.