Skip to content

Commit dba12e3

Browse files
committed
Add console print loop for Bad Apple, add grayscale
1 parent b184ce1 commit dba12e3

File tree

5 files changed

+103
-55
lines changed

5 files changed

+103
-55
lines changed

.gitignore

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
.idea/
2-
resources/
3-
resources/bad_apple
2+
resources/

bad_apple.py

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import time
2+
3+
import image_processor
4+
5+
# options
6+
fps = 30
7+
sec_time = 218.933333
8+
9+
ns_between_frames = 1 / 30 * 10 ** 9
10+
ns_init_sleep = 750000 # time to initiate sleep
11+
12+
if __name__ == '__main__':
13+
14+
result = 0
15+
frame = 0
16+
dropped_frames = []
17+
begin = time.time_ns()
18+
19+
while result is not None:
20+
before = time.time_ns()
21+
22+
result = image_processor.print_frame(f"resources/bad_apple/{frame}.png")
23+
24+
# to ensure video plays at 30 fps we need to calculate the time it has taken to print and reduce this
25+
# from wait so the next frame plays on time
26+
elapsed_time = time.time_ns() - before
27+
28+
# initiating sleep causes some ns to pass. remove this from time_to_wait to reduce inaccuracy from
29+
# ~2.5% (224 secs in execution) to ~-0.3% (218 secs in execution)
30+
ns_to_wait = ns_between_frames - elapsed_time - ns_init_sleep
31+
32+
if ns_to_wait < 0:
33+
dropped_frames.append(frame)
34+
ns_to_wait = 0
35+
36+
frame += 1
37+
38+
time.sleep(ns_to_wait * 10 ** -9)
39+
40+
end = time.time_ns()
41+
42+
deltasecs = (end - begin) / 10 ** 9
43+
44+
print(f"Took: {deltasecs} | "
45+
f"Accuracy: {(deltasecs - sec_time) / sec_time * 100}% | "
46+
f"Dropped frames: {dropped_frames}")

image_processor.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from PIL import Image
2+
3+
4+
def to_image(src):
5+
"""Returns a new Image instance to perform operations on."""
6+
return Image.open(src)
7+
8+
9+
def to_luminance(image, shrink):
10+
"""Returns a 2D-list of all rgba values mapped to the specified detail level."""
11+
width = int(image.size[0] / shrink)
12+
height = int(image.size[1] / shrink)
13+
14+
image = image.resize((width, height)).convert("L")
15+
16+
pixels = list(image.getdata())
17+
final = []
18+
19+
for y in range(height):
20+
final.append(pixels[(y * width):((y + 1) * width)])
21+
22+
return final
23+
24+
25+
grays = "#@$%&?!*~^;:'+=-_,.` "
26+
27+
28+
def to_char(luminance):
29+
"""Transforms a luminance value to an ASCII character."""
30+
return grays[int((1 - luminance / 255) * (len(grays) - 1))]
31+
32+
33+
def print_grid(pixels):
34+
"""Prints the final pixel grid."""
35+
to_chars = list(map(lambda row: list(map(to_char, row)), pixels))
36+
37+
print()
38+
39+
for row in to_chars:
40+
print("".join(row))
41+
42+
print()
43+
44+
45+
def print_frame(file):
46+
try:
47+
img = to_image(file)
48+
except FileNotFoundError:
49+
return None
50+
51+
dots = to_luminance(img, 8)
52+
53+
print_grid(dots)
54+
55+
return True

main.py

-52
This file was deleted.

speed_test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def to_rgba_getdata_resize(image, shrink):
6464
gdr = timeit.timeit(lambda: to_rgba_getdata_resize(to_image('resources/testing/test-image-2.png'), 8), number=n)
6565
print("=== getdata_resize ===")
6666
print(f"Total time: {gdr} seconds")
67-
print(f"Time per iter: {gdr / n} seconds") # 0.1 secs
67+
print(f"Time per iter: {gdr / n} seconds") # 0.01 secs
6868

6969
# gp = timeit.timeit(lambda: to_rgba_getpixel(to_image('testing/test-image-2.png')), number=n)
7070
# print("=== getpixel ===")

0 commit comments

Comments
 (0)