Tasks
- Quote:
Three may keep a secret, if two of them are dead.
- Objects: A key or a kite, depending on how you define "on the line".
Approach
I have done some image processing in Python before, so I chose to stick with that. I used a jupyter notebook for the interactivity. It took some experimenting (and manually converting binary) to get the right ordering of bits (LSB / MSB) for each step, but otherwise the tasks worked without major problems. In the end I cleaned up the code a little to be able to post it here without having to be too ashamed.
Code
import cv2
import matplotlib.pyplot as plt
test_b = cv2.imread("./SO-Challenge18-TestB.png") # one of the test images
img_1 = cv2.imread("./SO-Challenge18-Image1.png")
img_2 = cv2.imread("./SO-Challenge18-Image2.png")
print(f"'Test Test' should be {[c for c in "Test Test".encode("ascii")]}")
print(f"Test image shape: {test_b.shape}, total {test_b.size} bits")
print(f"Main image shape: {img_1.shape}, total {img_1.size} bits")
def get_int(bits):
val = 0
for i, bit in enumerate(bits[::-1]):
val = val | (bit << i)
return val
def get_flat_bits(img):
return img[:, :, ::-1].flatten() % 2
def decode_text(img):
bits = get_flat_bits(img)
assert bits[0] == 0 and bits[1] == 0
length = get_int(bits[2:18])
print(length)
chunks = bits[18:18+length].reshape((-1, 8))
chars = [chr(get_int(chunk)) for chunk in chunks]
return "".join(chars)
def decode_image(img):
bits = get_flat_bits(img)
assert bits[0] == 1 and bits[1] == 0
width = get_int(bits[2:18])
height = get_int(bits[18:34])
print(f"{width} x {height}")
image = bits[34 : 34 + width * height].reshape((width, height))
return image
part_1 = decode_text(img_1)
print(part_1)
part_2 = decode_image(img_2)
plt.imshow(part_2, cmap="gray")
plt.show()