148 lines
4.0 KiB
Python
148 lines
4.0 KiB
Python
#!/usr/bin/python
|
|
|
|
from PIL import Image
|
|
|
|
def invert(value):
|
|
return ''.join(["1" if x == "0" else "0" for x in value])
|
|
|
|
|
|
# Load Image
|
|
im = Image.open('QR3C_cropped.png')
|
|
pix = im.load()
|
|
|
|
tiles = 21
|
|
tileSize = im.size[0] // tiles
|
|
version = (tiles - 17) // 4
|
|
print("tiles=%d tileSize=%d version=%d" % (tiles, tileSize, version))
|
|
|
|
# Data Array
|
|
data = [[0 for x in range(tiles)] for y in range(tiles)]
|
|
|
|
# Fill data
|
|
# Black -> 111
|
|
# White -> 000
|
|
# Blue -> 110 ...
|
|
for y in range(tiles):
|
|
for x in range(tiles):
|
|
x_mid = x * tileSize + 0.5 * tileSize
|
|
y_mid = y * tileSize + 0.5 * tileSize
|
|
color = pix[x_mid, y_mid]
|
|
data[x][y] = invert("%d%d%d" % ( color[0] // 255, color[1] // 255, color[2] // 255 ))
|
|
|
|
def blackWhiteValue(string):
|
|
new_value = ""
|
|
if len(string) % 3 != 0:
|
|
print("Cannot return black white value of", string)
|
|
return new_value
|
|
|
|
for i in range(len(string) // 3):
|
|
new_value += string[i * 3]
|
|
|
|
return new_value
|
|
|
|
mask1 = [data[8][18], data[8][17], data[8][16]]
|
|
mask2 = [data[2][8], data[3][8], data[4][8]]
|
|
if mask1 != mask2:
|
|
print("masks do not match")
|
|
exit()
|
|
|
|
mask = [''.join(mask1[i][j] for i in range(3)) for j in range(3)]
|
|
print("Mask:", mask)
|
|
|
|
def apply_mask(x, y, bit, mask):
|
|
doInvert = False
|
|
if mask == "111":
|
|
doInvert = x % 3 == 0
|
|
elif mask == "110":
|
|
doInvert = (x + y) % 3 == 0
|
|
elif mask == "101":
|
|
doInvert = (x + y) % 2 == 0
|
|
elif mask == "100":
|
|
doInvert = y % 2 == 0
|
|
elif mask == "000":
|
|
doInvert = ((x*y) % 2) + ((x + y) % 3) == 0
|
|
|
|
return invert(bit) if doInvert else bit
|
|
|
|
def get_masked_value(x, y):
|
|
return ''.join([apply_mask(x, y, data[x][y][i], mask[i]) for i in range(3)])
|
|
|
|
def read_block(x, y, orientation):
|
|
indizes = []
|
|
if orientation == "UP":
|
|
indizes = [[0,0], [-1,0], [0,-1], [-1,-1], [0,-2], [-1,-2], [0, -3], [-1, -3]]
|
|
elif orientation == "LEFT_TOP":
|
|
indizes = [[0,0], [-1,0], [0,-1], [-1,-1], [-2,-1], [-3,-1], [-2, 0], [-3, 0]]
|
|
elif orientation == "DOWN":
|
|
indizes = [[0,0], [-1,0], [0,1], [-1,1], [0,2], [-1,2], [0, 3], [-1, 3]]
|
|
elif orientation == "LEFT_BOTTOM":
|
|
indizes = [[0,0], [-1,0], [0,1], [-1,1], [-2,1], [-3,1], [-2, 0], [-3, 0]]
|
|
|
|
return (''.join([get_masked_value(x + offset[0], y + offset[1]) for offset in indizes]))
|
|
|
|
def map_alphanumeric(x):
|
|
if x < 10:
|
|
return chr(ord('0') + x)
|
|
elif x < 36:
|
|
return chr(ord('A') + x - 10)
|
|
else:
|
|
special = { 36: " ", 37: "$", 38: "%", 39: "*", 40: "+", 41: "-", 42: ".", 43: "/", 44: ":" }
|
|
if x in special:
|
|
return special[x]
|
|
else:
|
|
print("unknown special character:", x)
|
|
return "?"
|
|
|
|
def decode_alphanumeric(x):
|
|
a = x // 45
|
|
b = x % 45
|
|
return map_alphanumeric(a) + map_alphanumeric(b)
|
|
|
|
encoding = blackWhiteValue(data[20][20] + data[19][20] + data[20][19] + data[19][19])
|
|
# encoding = data[20][20] + data[19][20] + data[20][19] + data[19][19]
|
|
# encoding = [get_masked_value(20, 20), get_masked_value(19, 20), get_masked_value(20, 19), get_masked_value(19, 19)]
|
|
print("Encoding:", encoding)
|
|
|
|
len_block = read_block(20, 18, "UP")
|
|
print("Length:", int(len_block, 2))
|
|
|
|
# 19 Blocks
|
|
|
|
blocks = ''.join([
|
|
read_block(20, 14, "UP"),
|
|
read_block(20, 10, "LEFT_TOP"),
|
|
read_block(18, 11, "DOWN"),
|
|
read_block(18, 15, "DOWN"),
|
|
read_block(18, 19, "LEFT_BOTTOM"),
|
|
read_block(16, 18, "UP"),
|
|
read_block(16, 14, "UP"),
|
|
read_block(16, 10, "LEFT_TOP"),
|
|
read_block(14, 11, "DOWN"),
|
|
read_block(14, 15, "DOWN")
|
|
])
|
|
|
|
channels = ["", "", ""]
|
|
|
|
blockSize = 3
|
|
for i in range(len(blocks) // blockSize):
|
|
channels[0] += blocks[i*3]
|
|
channels[1] += blocks[i*3+1]
|
|
channels[2] += blocks[i*3+2]
|
|
|
|
# chunk = int(blocks[blockSize*i:blockSize*i+blockSize],2)
|
|
# string += chr(chunk)
|
|
# string += decode_alphanumeric(chunk)
|
|
|
|
line = ""
|
|
for c in channels:
|
|
for i in range(len(c) // 8):
|
|
line += chr(int(c[i*8:i*8+8], 2))
|
|
print(line)
|
|
|
|
# print(len(blocks) /8)
|
|
# print(''.join(blocks))
|
|
|
|
|
|
# for x in range(tiles):
|
|
# print(''.join(data[x]))
|