Add a pretty-viewer for images.

This shows basic image information like dimensions, plus extracted EXIF tags
and other metadata.
This commit is contained in:
Aldo Cortesi 2012-03-26 11:26:02 +13:00
parent b6725ee802
commit a050eeef05
7 changed files with 52 additions and 1 deletions

View File

@ -1,5 +1,7 @@
import re import re, cStringIO
import urwid import urwid
from PIL import Image
from PIL.ExifTags import TAGS
import common import common
from .. import utils, encoding, flow from .. import utils, encoding, flow
from ..contrib import jsbeautifier from ..contrib import jsbeautifier
@ -22,6 +24,7 @@ VIEW_CONTENT_PRETTY_TYPE_XML = 2
VIEW_CONTENT_PRETTY_TYPE_URLENCODED = 3 VIEW_CONTENT_PRETTY_TYPE_URLENCODED = 3
VIEW_CONTENT_PRETTY_TYPE_MULTIPART = 4 VIEW_CONTENT_PRETTY_TYPE_MULTIPART = 4
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT = 5 VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT = 5
VIEW_CONTENT_PRETTY_TYPE_IMAGE = 6
CONTENT_PRETTY_NAMES = { CONTENT_PRETTY_NAMES = {
VIEW_CONTENT_PRETTY_TYPE_JSON: "JSON", VIEW_CONTENT_PRETTY_TYPE_JSON: "JSON",
@ -29,6 +32,7 @@ CONTENT_PRETTY_NAMES = {
VIEW_CONTENT_PRETTY_TYPE_URLENCODED: "URL-encoded", VIEW_CONTENT_PRETTY_TYPE_URLENCODED: "URL-encoded",
VIEW_CONTENT_PRETTY_TYPE_MULTIPART: "Multipart Form", VIEW_CONTENT_PRETTY_TYPE_MULTIPART: "Multipart Form",
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: "JavaScript", VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: "JavaScript",
VIEW_CONTENT_PRETTY_TYPE_IMAGE: "Image",
} }
CONTENT_TYPES_MAP = { CONTENT_TYPES_MAP = {
@ -39,6 +43,11 @@ CONTENT_TYPES_MAP = {
"application/x-www-form-urlencoded": VIEW_CONTENT_PRETTY_TYPE_URLENCODED, "application/x-www-form-urlencoded": VIEW_CONTENT_PRETTY_TYPE_URLENCODED,
"application/x-javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT, "application/x-javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
"application/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT, "application/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
"text/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
"image/png": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
"image/jpeg": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
"image/gif": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
"image/x-icon": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
} }
def trailer(clen, txt): def trailer(clen, txt):
@ -164,12 +173,47 @@ def view_javascript(hdrs, content):
return "JavaScript", _view_text(res) return "JavaScript", _view_text(res)
def view_image(hdrs, content):
try:
img = Image.open(cStringIO.StringIO(content))
except IOError:
return None
parts = [
("Format", str(img.format_description)),
("Size", "%s x %s px"%img.size),
("Mode", str(img.mode)),
]
for i in sorted(img.info.keys()):
if i != "exif":
parts.append(
(str(i), str(img.info[i]))
)
if hasattr(img, "_getexif"):
ex = img._getexif()
if ex:
for i in sorted(ex.keys()):
tag = TAGS.get(i, i)
parts.append(
(str(tag), str(ex[i]))
)
clean = []
for i in parts:
clean.append([utils.cleanBin(i[0]), utils.cleanBin(i[1])])
fmt = common.format_keyvals(
clean,
key = "header",
val = "text"
)
return "%s image"%img.format, fmt
PRETTY_FUNCTION_MAP = { PRETTY_FUNCTION_MAP = {
VIEW_CONTENT_PRETTY_TYPE_XML: view_xmlish, VIEW_CONTENT_PRETTY_TYPE_XML: view_xmlish,
VIEW_CONTENT_PRETTY_TYPE_JSON: view_json, VIEW_CONTENT_PRETTY_TYPE_JSON: view_json,
VIEW_CONTENT_PRETTY_TYPE_URLENCODED: view_urlencoded, VIEW_CONTENT_PRETTY_TYPE_URLENCODED: view_urlencoded,
VIEW_CONTENT_PRETTY_TYPE_MULTIPART: view_multipart, VIEW_CONTENT_PRETTY_TYPE_MULTIPART: view_multipart,
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: view_javascript, VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: view_javascript,
VIEW_CONTENT_PRETTY_TYPE_IMAGE: view_image,
} }
def get_view_func(viewmode, pretty_type, hdrs, content): def get_view_func(viewmode, pretty_type, hdrs, content):

BIN
test/data/image-err1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
test/data/image.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
test/data/image.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
test/data/image.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
test/data/image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@ -83,6 +83,13 @@ class uContentView(libpry.AutoTree):
def test_view_raw(self): def test_view_raw(self):
assert cv.view_hex([], "foo") assert cv.view_hex([], "foo")
def test_view_image(self):
assert cv.view_image([], file("data/image.png").read())
assert cv.view_image([], file("data/image.gif").read())
assert cv.view_image([], file("data/image-err1.jpg").read())
assert cv.view_image([], file("data/image.ico").read())
assert not cv.view_image([], "flibble")
def test_view_multipart(self): def test_view_multipart(self):
v = """ v = """
--AaB03x --AaB03x