-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdither_python.py
More file actions
169 lines (138 loc) · 3.89 KB
/
dither_python.py
File metadata and controls
169 lines (138 loc) · 3.89 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
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
'''
Dither style for any picture
Author: Inigo Iribarren
Date: 30-03-2020
Usage:
dither_python.py [-c COLOR] [-b BAYER SIZE] [-s SCALE] [-r RESIZE_X RESIZE_Y] filename.ex
'''
from PIL import Image
import numpy as np
import argparse
def cli() -> argparse.Namespace:
parser = argparse.ArgumentParser(
prog='dither_python',
description='Creates a copy of a selected image using bayer dithering style'
)
parser.add_argument(
'file',
type=str,
help='Picture that will be transformed.'
)
parser.add_argument(
'-c',
'--color',
action='store_true', help='Makes the dithering in color instead of B&W'
)
parser.add_argument(
'-r',
'--resize',
default=(),
nargs='+',
type=int,
help='New size of the ouput image.'
)
parser.add_argument(
'-s',
'--scale',
default=1.0,
type=float,
help='Scale factor for the ouput image.'
)
parser.add_argument(
'-b',
'--bayer',
default=2,
type=int,
help='Dimension of the bayer matrix.'
)
return parser.parse_args()
def get_bayer(dimension):
'''Returns a bayer matrix
Returns a bayer matrix of N dimension that will be used as a template for
the dithering transformation.
'''
# Dimmension 1 has to be fixed cause that is 'dirty'
if dimension == 1:
bayer = [
[127, 127],
[127, 127]
]
elif dimension == 2:
bayer = [
[ 51, 153],
[204, 102]
]
elif dimension == 3:
bayer = [
[ 25, 150, 75],
[200, 125, 225],
[100, 175, 50]
]
elif dimension == 4:
bayer = [
[ 15, 135, 45, 165],
[195, 75, 225, 105],
[ 60, 180, 30, 150],
[240, 120, 210, 90]
]
else:
print('ERROR: not a valid bayer dimension')
exit()
return bayer
def dither_bw(data, bayer):
'''Substitues in black and white, pixel by pixels, all the image using the bayer matrix
'''
o_data = np.zeros(data.shape)
for x in range(0, data.shape[0]):
for y in range(0, data.shape[1]):
if data[x,y] > bayer[x%len(bayer)][y%len(bayer)]:
o_data[x,y] = 255
else:
o_data[x,y] = 0
return o_data
def dither_color(data, bayer):
'''Substitues in color, pixel by pixels, all the image using the bayer matrix
'''
o_data = np.zeros(data.shape)
for x in range(0, data.shape[0]):
for y in range(0, data.shape[1]):
for color in range(0, data.shape[2]):
if data[x,y,color] > bayer[x%len(bayer)][y%len(bayer)]:
o_data[x,y,color] = 255
else:
o_data[x,y,color] = 0
return o_data
def main():
# Parse arguments
args = cli()
# Get the bayer matrix
b_matrix = get_bayer(args.bayer)
# Read image
if not args.color:
img = Image.open(args.file).convert('L')
else:
img = Image.open(args.file).convert('RGB')
# Resize if necessary
if args.resize:
w = args.size[0]
h = args.size[1]
else:
w, h = img.size
# Scales the image by factor S
o_w = int(w * args.scale)
o_h = int(h * args.scale)
img = img.resize((o_w, o_h), Image.NEAREST)
# Transform img to array
d_img = np.array(img)
# Transform pixel by pixel
if not args.color:
d_new = dither_bw(d_img, b_matrix)
if args.color:
d_new = dither_color(d_img, b_matrix)
# New image based on dithered data
img_new = Image.fromarray(d_new.astype(np.uint8))
# Saves the new image
o_name = args.file.split('.')[0] + '_bayer' + str(args.bayer) + '.png'
img_new.save(o_name)
if __name__ == '__main__':
main()