forked from ghallak/jpeg-python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.py
126 lines (97 loc) · 3.96 KB
/
utils.py
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
import numpy as np
def load_quantization_table(component):
# Quantization Table for: Photoshop - (Save For Web 080)
# (http://www.impulseadventure.com/photo/jpeg-quantization.html)
if component == 'lum':
q = np.array([[2, 2, 2, 2, 3, 4, 5, 6],
[2, 2, 2, 2, 3, 4, 5, 6],
[2, 2, 2, 2, 4, 5, 7, 9],
[2, 2, 2, 4, 5, 7, 9, 12],
[3, 3, 4, 5, 8, 10, 12, 12],
[4, 4, 5, 7, 10, 12, 12, 12],
[5, 5, 7, 9, 12, 12, 12, 12],
[6, 6, 9, 12, 12, 12, 12, 12]])
elif component == 'chrom':
q = np.array([[3, 3, 5, 9, 13, 15, 15, 15],
[3, 4, 6, 11, 14, 12, 12, 12],
[5, 6, 9, 14, 12, 12, 12, 12],
[9, 11, 14, 12, 12, 12, 12, 12],
[13, 14, 12, 12, 12, 12, 12, 12],
[15, 12, 12, 12, 12, 12, 12, 12],
[15, 12, 12, 12, 12, 12, 12, 12],
[15, 12, 12, 12, 12, 12, 12, 12]])
q = np.array([[1, 1, 1, 1, 13, 15, 15, 15],
[1, 1, 1, 11, 14, 12, 12, 12],
[1, 1, 1, 14, 12, 12, 12, 12],
[1, 11, 14, 12, 12, 12, 12, 12],
[13, 14, 12, 12, 12, 12, 12, 12],
[15, 12, 12, 12, 12, 12, 12, 12],
[15, 12, 12, 12, 12, 12, 12, 12],
[15, 12, 12, 12, 12, 12, 12, 12]])
else:
raise ValueError((
"component should be either 'lum' or 'chrom', "
"but '{comp}' was found").format(comp=component))
return q
def zigzag_points(rows, cols):
# constants for directions
UP, DOWN, RIGHT, LEFT, UP_RIGHT, DOWN_LEFT = range(6)
# move the point in different directions
def move(direction, point):
return {
UP: lambda point: (point[0] - 1, point[1]),
DOWN: lambda point: (point[0] + 1, point[1]),
LEFT: lambda point: (point[0], point[1] - 1),
RIGHT: lambda point: (point[0], point[1] + 1),
UP_RIGHT: lambda point: move(UP, move(RIGHT, point)),
DOWN_LEFT: lambda point: move(DOWN, move(LEFT, point))
}[direction](point)
# return true if point is inside the block bounds
def inbounds(point):
return 0 <= point[0] < rows and 0 <= point[1] < cols
# start in the top-left cell
point = (0, 0)
# True when moving up-right, False when moving down-left
move_up = True
for i in range(rows * cols):
yield point
if move_up:
if inbounds(move(UP_RIGHT, point)):
point = move(UP_RIGHT, point)
else:
move_up = False
if inbounds(move(RIGHT, point)):
point = move(RIGHT, point)
else:
point = move(DOWN, point)
else:
if inbounds(move(DOWN_LEFT, point)):
point = move(DOWN_LEFT, point)
else:
move_up = True
if inbounds(move(DOWN, point)):
point = move(DOWN, point)
else:
point = move(RIGHT, point)
def bits_required(n):
n = abs(n)
result = 0
while n > 0:
n >>= 1
result += 1
return result
def binstr_flip(binstr):
# check if binstr is a binary string
if not set(binstr).issubset('01'):
raise ValueError("binstr should have only '0's and '1's")
return ''.join(map(lambda c: '0' if c == '1' else '1', binstr))
def uint_to_binstr(number, size):
return bin(number)[2:][-size:].zfill(size)
def int_to_binstr(n):
if n == 0:
return ''
binstr = bin(abs(n))[2:]
# change every 0 to 1 and vice verse when n is negative
return binstr if n > 0 else binstr_flip(binstr)
def flatten(lst):
return [item for sublist in lst for item in sublist]