67 lines
1.8 KiB
Markdown
67 lines
1.8 KiB
Markdown
# Quick Response - misc
|
|
|
|

|
|
|
|
|
|
fridgebuyer
|
|
|
|
- The QR is 29x29 == version 3
|
|
- Each module = 32x32 px
|
|
- What should be solid is alternated. The 7x7 finder patterns should be solid but are not visible in the 3 corners (top left, bottom left, top right)
|
|
- What should be alternated are solid lines (timing strips)
|
|
- So the original QR was likely XORed with a Checkerboard pattern
|
|
- https://www.pclviewer.com/rs2/qrmasking.htm Mask 000: (i + j) mod 2 = 0 is this
|
|
- But this was applied to entire qr code, not only to the data region
|
|
- So need to XOR every module with (row + col) % 2 again.
|
|
|
|
### sol
|
|
|
|
```
|
|
from PIL import Image
|
|
import numpy as np
|
|
from pyzbar.pyzbar import decode
|
|
|
|
img = Image.open("quick-response.png").convert("RGB")
|
|
arr = np.array(img)
|
|
|
|
# extract module grid
|
|
module_size = 32
|
|
n = 29
|
|
dark = np.array([20, 22, 27])
|
|
|
|
grid = np.zeros((n, n), dtype=int)
|
|
for r in range(n):
|
|
for c in range(n):
|
|
cy = r * module_size + module_size // 2
|
|
cx = c * module_size + module_size // 2
|
|
pixel = arr[cy, cx]
|
|
if np.sum((pixel.astype(int) - dark.astype(int)) ** 2) < 100:
|
|
grid[r, c] = 1
|
|
|
|
# XOR (i + j) mod 2 = 0
|
|
for r in range(n):
|
|
for c in range(n):
|
|
grid[r, c] ^= (r + c) % 2
|
|
|
|
# write fixed QR code
|
|
scale = 10
|
|
border = 4
|
|
total = (n + 2 * border) * scale
|
|
out = Image.new("L", (total, total), 255)
|
|
px = out.load()
|
|
for r in range(n):
|
|
for c in range(n):
|
|
if grid[r, c] == 1:
|
|
for dy in range(scale):
|
|
for dx in range(scale):
|
|
px[(c + border) * scale + dx, (r + border) * scale + dy] = 0
|
|
|
|
result = decode(out)
|
|
for r in result:
|
|
print(r.data.decode())
|
|
|
|
```
|
|
|
|

|
|
|
|
**gigem{d1d_y0u_n0t1c3_th3_t1m1n9_b175}**
|