-
Notifications
You must be signed in to change notification settings - Fork 109
/
cpngfilters.pyx
134 lines (110 loc) · 3.41 KB
/
cpngfilters.pyx
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
#cython: boundscheck=False
#cython: wraparound=False
from libc.stdlib cimport abs as c_abs
cimport cpython.array
# TODO: I don't know how can I not return any value (void doesn't work)
cpdef int undo_filter_sub(int filter_unit, unsigned char[:] scanline,
unsigned char[:] previous, unsigned char[:] result) nogil:
"""Undo sub filter."""
cdef int l = result.shape[0]
cdef int ai = 0
cdef unsigned char x, a
# Loops starts at index fu. Observe that the initial part
# of the result is already filled in correctly with
# scanline.
for i in range(filter_unit, l):
x = scanline[i]
a = result[ai]
result[i] = (x + a) & 0xff
ai += 1
return 0
cpdef int undo_filter_up(int filter_unit, unsigned char[:] scanline,
unsigned char[:] previous, unsigned char[:] result) nogil:
"""Undo up filter."""
cdef int i
cdef int l = result.shape[0]
cdef unsigned char x, b
for i in range(l):
x = scanline[i]
b = previous[i]
result[i] = (x + b) & 0xff
return 0
cpdef int undo_filter_average(int filter_unit, unsigned char[:] scanline,
unsigned char[:] previous, unsigned char[:] result) nogil:
"""Undo up filter."""
cdef int i, ai
cdef int l = result.shape[0]
cdef unsigned char x, a, b
ai = -filter_unit
for i in range(l):
x = scanline[i]
if ai < 0:
a = 0
else:
a = result[ai]
b = previous[i]
result[i] = (x + ((a + b) >> 1)) & 0xff
ai += 1
return 0
cpdef int undo_filter_paeth(int filter_unit, unsigned char[:] scanline,
unsigned char[:] previous, unsigned char[:] result) nogil:
"""Undo Paeth filter."""
# Also used for ci.
cdef int ai = -filter_unit
cdef int l = result.shape[0]
cdef int i, pa, pb, pc, p
cdef unsigned char x, a, b, c, pr
for i in range(l):
x = scanline[i]
if ai < 0:
a = c = 0
else:
a = result[ai]
c = previous[ai]
b = previous[i]
p = a + b - c
pa = c_abs(p - a)
pb = c_abs(p - b)
pc = c_abs(p - c)
if pa <= pb and pa <= pc:
pr = a
elif pb <= pc:
pr = b
else:
pr = c
result[i] = (x + pr) & 0xff
ai += 1
return 0
cpdef int convert_rgb_to_rgba(unsigned char[:] row, unsigned char[:] result) nogil:
cdef int i, l, j, k
l = min(row.shape[0] / 3, result.shape[0] / 4)
for i in range(l):
j = i * 3
k = i * 4
result[k] = row[j]
result[k + 1] = row[j + 1]
result[k + 2] = row[j + 2]
return 0
cpdef int convert_l_to_rgba(unsigned char[:] row, unsigned char[:] result) nogil:
cdef int i, l, j, k, lum
l = min(row.shape[0], result.shape[0] / 4)
for i in range(l):
j = i
k = i * 4
lum = row[j]
result[k] = lum
result[k + 1] = lum
result[k + 2] = lum
return 0
cpdef int convert_la_to_rgba(unsigned char[:] row, unsigned char[:] result) nogil:
cdef int i, l, j, k, lum
l = min(row.shape[0] / 2, result.shape[0] / 4)
for i in range(l):
j = i * 2
k = i * 4
lum = row[j]
result[k] = lum
result[k + 1] = lum
result[k + 2] = lum
result[k + 3] = row[j + 1]
return 0