-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlevels.py
More file actions
122 lines (93 loc) · 3.23 KB
/
levels.py
File metadata and controls
122 lines (93 loc) · 3.23 KB
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
# adjust levels to fill histogram
# Kevin Cazabon, 1999. kcazabon at rogers.wave.ca kcaza at cymbolic.com
#
# https://mail.python.org/pipermail/image-sig/2005-September/003514.html
# http://code.activestate.com/lists/python-image-sig/%3cs6c95fdd.013@cymbolic.com%3e/
def levels(data, all_same = 1, clip = 0):
"""Adjust image levels
- checks the histogram, determines the actual brightness range used
in the image for each channel
- scales the data to fill the full 0-255 range either by scaling
each channel individually, or by scaling them equally (to the
lowest common denomonator)
:param all_same: 0 = scale each channel individually, 1 = scale all
channels the same
:param clip: integer, if there's less than this number of pixels at
the minimum/maximum brightness level found, don't use
them to calculate the levels adjustment (i.e. they get
clipped off the image to pure black/white) default is
0. This is useful if you have a few 'dark' or 'bright'
pixels that actually are not relevant detail and are
causing the scaling to not properly fill up the
histogram.
"""
if data.mode not in ['RGB', 'CMYK']:
return data
lut = makelut(data, all_same, clip)
data = data.point(lut)
return data
def find_hi_lo(lut, clip):
min = None
max = None
for i in range(len(lut)):
if lut[i] > clip:
min = i
break
lut.reverse()
for i in range(len(lut)):
if lut[i] > clip:
max = 255 - i
break
return min, max
def scale(channels, min, max):
lut = []
for i in range (channels):
for i in range(256):
value = int((i - min)*(255.0/float(max-min)))
if value < 0:
value = 0
if value > 255:
value = 255
lut.append(value)
return lut
def makelut(data, all_same, clip):
import PIL.Image
histogram = data.histogram()
lut = []
r, g, b, k = [], [], [], []
channels = len(histogram) // 256
for i in range(256):
r.append(histogram[i])
g.append(histogram[256+i])
b.append(histogram[512+i])
if channels == 4:
for i in range(256):
k.append(histogram[768+i])
rmin, rmax = find_hi_lo(r, clip)
gmin, gmax = find_hi_lo(g, clip)
bmin, bmax = find_hi_lo(b, clip)
if channels == 4:
kmin, kmax = find_hi_lo(k)
else:
kmin, kmax = 128, 128
if all_same == 1:
min_max = [rmin, gmin, bmin, kmin, rmax, gmax, bmax, kmax]
min_max.sort()
lut = scale(channels, min_max[0], min_max[-1])
else:
r_lut = scale(1, rmin, rmax)
g_lut = scale(1, gmin, gmax)
b_lut = scale(1, bmin, bmax)
if channels == 4:
k_lut = scale(1, kmin, kmax)
lut = []
for i in range (256):
lut.append(r_lut[i])
for i in range (256):
lut.append(g_lut[i])
for i in range (256):
lut.append(b_lut[i])
if channels == 4:
for i in range (256):
lut.append(k_lut[i])
return lut