Skip to content

Instantly share code, notes, and snippets.

@lletfrix
Created September 16, 2021 15:46
Show Gist options
  • Save lletfrix/7c72381895146702f8129e666e747e8a to your computer and use it in GitHub Desktop.
Save lletfrix/7c72381895146702f8129e666e747e8a to your computer and use it in GitHub Desktop.
Rounded QR Code scripts
import math
import numpy as np
def get_horizontal_instructions(matrix):
instructions = []
for row in matrix:
currentVal = row[0]
start = 0
rowInstructions = []
for (i, c) in enumerate(row[1:]+[2]):
if c != currentVal:
rowInstructions.append((start, i+1, currentVal))
start = i+1
currentVal = c
instructions.append(rowInstructions)
return instructions
def get_horizontal_paths(horizontal_instructions):
paths = []
for (i, ins_row) in enumerate(horizontal_instructions):
for instruction in ins_row:
start, end, val = instruction
if (val):
d = f'M {start*4} {i*4} m 2 0 c -1.7 0 -2 0.3 -2 2 c 0 1.7 0.3 2 2 2'
walk = end - start - 1
if walk:
d += f' h {walk*4} c 1.7 0 2 -0.3 2 -2 c 0 -1.7 -0.3 -2 -2 -2 h -{walk*4} Z'
else:
d += f' c 1.7 0 2 -0.3 2 -2 c 0 -1.7 -0.3 -2 -2 -2 Z'
paths.append(f'<path d="{d} Z" fill="black"/>')
return paths
def get_horizontal_svg(matrix):
width = len(matrix[0])
height = len(matrix)
svg = f'<svg xmlns="http://www.w3.org/2000/svg" width="{height * 10}" height="{height * 10}" fill="none" viewBox="0 0 {width * 4} {height * 4}">\n'
paths = get_horizontal_paths(get_horizontal_instructions(matrix))
for path in paths:
svg += f' {path}\n'
svg += '</svg>'
return svg
def get_vertical_instructions(matrix):
transposed = np.array(matrix).transpose().tolist()
return get_horizontal_instructions(transposed)
def get_vertical_paths(vertical_instructions):
paths = []
for (i, ins_row) in enumerate(vertical_instructions):
for instruction in ins_row:
start, end, val = instruction
if (val):
d = f'M {i*4} {start*4} m 2 0 c -1.7 0 -2 0.3 -2 2' # C0
walk = end - start - 1
if walk:
d += f' v {walk*4} c 0 1.7 0.3 2 2 2 c 1.7 0 2 -0.3 2 -2 v -{walk*4} c 0 -1.7 -0.3 -2 -2 -2 Z'
else:
d += f' c 0 1.7 0.3 2 2 2 c 1.7 0 2 -0.3 2 -2 c 0 -1.7 -0.3 -2 -2 -2 Z'
paths.append(f'<path d="{d} Z" fill="black"/>')
return paths
def get_vertical_svg(matrix):
width = len(matrix[0])
height = len(matrix)
svg = f'<svg xmlns="http://www.w3.org/2000/svg" width="{height * 10}" height="{height * 10}" fill="none" viewBox="0 0 {width * 4} {height * 4}">\n'
paths = get_vertical_paths(get_vertical_instructions(matrix))
for path in paths:
svg += f' {path}\n'
svg += '</svg>'
return svg
def get_crossed_svg(matrix):
width = len(matrix[0])
height = len(matrix)
svg = f'<svg xmlns="http://www.w3.org/2000/svg" width="{height * 10}" height="{height * 10}" fill="none" viewBox="0 0 {width * 4} {height * 4}">\n'
svg += '<g>\n'
paths = get_vertical_paths(get_vertical_instructions(matrix))
for path in paths:
svg += f' {path}\n'
svg += '</g>\n'
svg += '<g>\n'
paths = get_horizontal_paths(get_horizontal_instructions(matrix))
for path in paths:
svg += f' {path}\n'
svg += '</g>\n'
svg += '</svg>'
return svg
'''
<svg xmlns="http://www.w3.org/2000/svg" x="16" y="16" viewBox="0 0 28 28" fill="none" height="28" width="28">
<path d="M8 14C8 8.9 8.9 8 14 8C19.1 8 20 8.9 20 14C20 19.1 19.1 20 14 20C8.9 20 8 19.1 8 14Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 0C2.1 0 0 2.1 0 14C0 25.9 2.1 28 14 28C25.9 28 28 25.9 28 14C28 2.1 25.9 0 14 0ZM4 14C4 11.0843 4.13416 9.05342 4.43282 7.59427C4.72259 6.17856 5.1032 5.62865 5.36593 5.36593C5.62865 5.1032 6.17856 4.72259 7.59427 4.43282C9.05342 4.13416 11.0843 4 14 4C16.9157 4 18.9466 4.13416 20.4057 4.43282C21.8214 4.72259 22.3713 5.1032 22.6341 5.36593C22.8968 5.62865 23.2774 6.17856 23.5672 7.59427C23.8658 9.05342 24 11.0843 24 14C24 16.9157 23.8658 18.9466 23.5672 20.4057C23.2774 21.8214 22.8968 22.3713 22.6341 22.6341C22.3713 22.8968 21.8214 23.2774 20.4057 23.5672C18.9466 23.8658 16.9157 24 14 24C11.0843 24 9.05342 23.8658 7.59427 23.5672C6.17856 23.2774 5.62865 22.8968 5.36593 22.6341C5.1032 22.3713 4.72259 21.8214 4.43282 20.4057C4.13416 18.9466 4 16.9157 4 14Z" fill="black"/>
</svg>
'''
def get_custom_capture_group(x, y):
return(f'''<svg xmlns="http://www.w3.org/2000/svg" x="{x}" y="{y}" viewBox="0 0 28 28" fill="none" height="28" width="28">
<path d="M8 14C8 8.9 8.9 8 14 8C19.1 8 20 8.9 20 14C20 19.1 19.1 20 14 20C8.9 20 8 19.1 8 14Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 0C2.1 0 0 2.1 0 14C0 25.9 2.1 28 14 28C25.9 28 28 25.9 28 14C28 2.1 25.9 0 14 0ZM4 14C4 11.0843 4.13416 9.05342 4.43282 7.59427C4.72259 6.17856 5.1032 5.62865 5.36593 5.36593C5.62865 5.1032 6.17856 4.72259 7.59427 4.43282C9.05342 4.13416 11.0843 4 14 4C16.9157 4 18.9466 4.13416 20.4057 4.43282C21.8214 4.72259 22.3713 5.1032 22.6341 5.36593C22.8968 5.62865 23.2774 6.17856 23.5672 7.59427C23.8658 9.05342 24 11.0843 24 14C24 16.9157 23.8658 18.9466 23.5672 20.4057C23.2774 21.8214 22.8968 22.3713 22.6341 22.6341C22.3713 22.8968 21.8214 23.2774 20.4057 23.5672C18.9466 23.8658 16.9157 24 14 24C11.0843 24 9.05342 23.8658 7.59427 23.5672C6.17856 23.2774 5.62865 22.8968 5.36593 22.6341C5.1032 22.3713 4.72259 21.8214 4.43282 20.4057C4.13416 18.9466 4 16.9157 4 14Z" fill="black"/>
</svg>''')
def get_custom_svg(svg, matrix):
width = len(matrix[0])
height = len(matrix)
custom_svg = svg[:-6]
custom_svg += get_custom_capture_group(16, 16)
custom_svg += get_custom_capture_group(16, 4*(height-11))
custom_svg += get_custom_capture_group(4*(width-11), 16)
return custom_svg+svg[-6:]
def clear_capture_groups(code_matrix):
def clear7x7(start, matrix):
for i in range(0, 7):
for j in range(0, 7):
matrix[start[0]+i][start[1]+j] = False
clear7x7((4, 4), code_matrix)
clear7x7((4, -11), code_matrix)
clear7x7((-11, 4), code_matrix)
if __name__ == "__main__":
import qrcode
import sys
qr = qrcode.QRCode( version=None, box_size=1, border=4, error_correction=qrcode.constants.ERROR_CORRECT_M)
# qr.add_data('https://app.getfesto.party/accounts/links/places?uuid=89f21287-e29b-4632-9563-0f5c03e57abe')
qr.add_data(sys.argv[1])
qr.make(fit=True)
mtx = qr.get_matrix()
clear_capture_groups(mtx)
# with open('qrcode_vertical.svg', 'w') as f:
# f.write(get_vertical_svg(mtx))
# with open('qrcode_horizontal.svg', 'w') as f:
# f.write(get_horizontal_svg(mtx))
# with open('qrcode.svg', 'w') as f:
# f.write(get_crossed_svg(mtx))
with open('qrcode_custom.svg', 'w') as f:
crossed = get_crossed_svg(mtx)
f.write(get_custom_svg(crossed, mtx))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment