forked from srossross/misc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
histogram
179 lines (138 loc) · 4.47 KB
/
histogram
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/python
"""Usage: %s [file] [file]*
Draws RGB histograms and displays them.
If the directory %r exists, the histograms are stored in this
directory and not displayed.
Configuration file is %r
Author: Ilan Schnell, 2007"""
import os
import Image, ImageDraw, ImageFont
from ImageColor import getrgb as rgb
# true type font
TTF = "/home/fonts/ttf/courbd.ttf"
# background color
BG = "#000"
# background color of all histograms
HIST_BG = "#888"
# color of filename
FILE_FG = "#fff"
# color of image size, e.g. the text "3008 x 2000"
SIZE_FG = "#7af"
# height of all histograms (in pixels)
HIST_HEIGHT = 175
# margens (in pixels)
MARGENS = 5
# text size (in pixels)
# Note: 0 means no text
TEXT_SIZE = 20
# directory to put histograms
# Note: If directory is not accessible, histograms are stored
# in TMP_FILE and displayed with the VIEWCMD, and removed
# when the program is finished.
HIST_DIR = "hist/"
def histImg(height, rgbwHist, i):
"""
Returns an image of size 256 x height containing one histogram.
The list rgbwHist always contains four bands: red, green, blue and white
The integer i selects which band is plotted: 0 1 2 3
"""
if i<3:
dispHist = rgbwHist[256 * i:256 * (i + 1)]
col = rgb(['#f00','#0f0','#00f'][i])
else:
dispHist = rgbwHist[256 * 3:]
col = rgb('#fff')
res = Image.new('RGB', (256, height), rgb(HIST_BG))
if sum(dispHist):
maxv = max(dispHist)
dispHist = [int(0.95 * height * x / maxv) for x in dispHist]
draw = ImageDraw.Draw(res)
for j in xrange(256):
draw.line((j, height - 1, j, height - 1 - dispHist[j]), fill=col)
return res
def ratio(size):
w, h = size
return float(w)/h
def getRGBWhist(image):
"""
Returns the RGBW (see above) histogram list which is always of length 1024.
When the image mode can not be used to retrieve this information,
None is returned.
"""
try:
hist = image.histogram()
mode = image.mode
except:
print "An error occurred while reading."
return
if mode=='L':
return 3 * 256 * [0] + hist[:256]
elif mode in ['RGB', 'RGBA']:
return hist[:3 * 256] + [sum(hist[256 * c + j] for c in xrange(3))
for j in xrange(256)]
else:
print 'Mode %r is not supported.' % mode
return
def mkHistImg(image, name):
"""
Returns the complete result image, i.e. with the original image, the
histograms and text. Again, if something goes wrong, None is returned.
"""
rgbwhist = getRGBWhist(image)
if not rgbwhist:
return
nh = 4 * HIST_HEIGHT + 5 * MARGENS
if TEXT_SIZE: nh += 2 * (TEXT_SIZE + MARGENS)
nw = int(nh * ratio(image.size))
out = Image.new('RGB' + ('A' if len(image.getbands()) == 4 else ''),
(nw + 256 + 2 * MARGENS, nh), rgb(BG))
out.paste(image.resize((nw, nh), Image.BILINEAR),
(0, 0, nw, nh))
x0, y0 = nw+MARGENS, MARGENS
for i in xrange(4):
out.paste(histImg(HIST_HEIGHT, rgbwhist, i),
(x0, y0, x0 + 256, y0 + HIST_HEIGHT))
y0 += HIST_HEIGHT + MARGENS
if TEXT_SIZE:
draw = ImageDraw.Draw(out)
draw.text((x0, y0), name,
fill = rgb(FILE_FG), font = _font)
draw.text((x0, y0 + TEXT_SIZE + MARGENS), '%s x %s' % image.size,
fill = rgb(SIZE_FG), font = _font)
return out
def process(name):
"""
Processes the file named.
"""
print 'processing %r ...' % name
try:
image = Image.open(name)
except IOError:
print "Can't read/identify file %r." % name
return
out = mkHistImg(image, name)
if not out:
return
if os.access(HIST_DIR, os.W_OK):
out.save(HIST_DIR + name + '.png')
else:
import tempfile
tmpfile = tempfile.mkstemp(".png")[1]
out.save(tmpfile)
print("%s" % tmpfile)
if __name__ == '__main__':
import sys, os.path
files = sys.argv[1:]
if not HIST_DIR.endswith('/'):
print "Warning: HIST_DIR %r does not have trailing '/'." % HIST_DIR
if not files:
print __doc__ % (sys.argv[0], HIST_DIR, rc_file)
sys.exit(2)
if TEXT_SIZE:
try:
_font = ImageFont.truetype(TTF, TEXT_SIZE)
except:
print 'Warning: Could not read %r, switching text off.' % TTF
TEXT_SIZE = 0
for f in files:
process(f)