feat: QR 테스트 v2 - 더 많은 변형 (크기, 밀도, 파라미터)

This commit is contained in:
시골약사 2026-01-29 20:15:13 +09:00
parent 161f826380
commit a4cfcb6bde

View File

@ -0,0 +1,281 @@
"""
ESC/POS QR 코드 인쇄 방식 테스트 v2
많은 변형 시도 (크기, 밀도, 파라미터)
"""
import socket
import qrcode
import time
# 프린터 설정
PRINTER_IP = "192.168.0.174"
PRINTER_PORT = 9100
# 테스트 URL (더 짧게)
TEST_URL = "https://bit.ly/test"
def send_to_printer(data, method_name):
"""프린터로 데이터 전송"""
try:
print(f"\n[{method_name}] 전송 중... ({len(data)} bytes)")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)
sock.connect((PRINTER_IP, PRINTER_PORT))
sock.sendall(data)
sock.close()
print(f"[{method_name}] ✅ 완료")
time.sleep(1.5)
return True
except Exception as e:
print(f"[{method_name}] ❌ 실패: {e}")
return False
def method_1_tiny_qr_escstar():
"""방법 1: 아주 작은 QR (30x30) + ESC *"""
ESC = b'\x1b'
GS = b'\x1d'
commands = []
commands.append(ESC + b'@')
commands.append("\n================================\n".encode('euc-kr'))
commands.append(" *** 방법 1 ***\n".encode('euc-kr'))
commands.append(" 작은 QR 30x30 (ESC *)\n".encode('euc-kr'))
commands.append("================================\n\n".encode('euc-kr'))
# 30x30 QR
qr = qrcode.QRCode(version=1, box_size=1, border=1)
qr.add_data(TEST_URL)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white").resize((30, 30)).convert('1')
width, height = img.size
pixels = img.load()
# ESC * m=0 (8-dot single-density)
for y in range(0, height, 8):
commands.append(ESC + b'*' + bytes([0, width & 0xFF, (width >> 8) & 0xFF]))
for x in range(width):
byte = 0
for bit in range(min(8, height - y)):
if pixels[x, y + bit] == 0:
byte |= (1 << (7 - bit))
commands.append(bytes([byte]))
commands.append(b'\n')
commands.append(f"\nURL: {TEST_URL}\n\n\n".encode('euc-kr'))
commands.append(GS + b'V' + bytes([1]))
return b''.join(commands)
def method_2_medium_qr_escstar_mode32():
"""방법 2: 중간 QR (50x50) + ESC * mode 32"""
ESC = b'\x1b'
GS = b'\x1d'
commands = []
commands.append(ESC + b'@')
commands.append("\n================================\n".encode('euc-kr'))
commands.append(" *** 방법 2 ***\n".encode('euc-kr'))
commands.append(" 중간 QR 50x50 (ESC * m=32)\n".encode('euc-kr'))
commands.append("================================\n\n".encode('euc-kr'))
# 50x50 QR
qr = qrcode.QRCode(version=1, box_size=2, border=1)
qr.add_data(TEST_URL)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white").resize((50, 50)).convert('1')
width, height = img.size
pixels = img.load()
# ESC * m=32 (24-dot single-density)
for y in range(0, height, 24):
commands.append(ESC + b'*' + bytes([32, width & 0xFF, (width >> 8) & 0xFF]))
for x in range(width):
byte1 = byte2 = byte3 = 0
for bit in range(min(24, height - y)):
if pixels[x, y + bit] == 0:
if bit < 8:
byte1 |= (1 << (7 - bit))
elif bit < 16:
byte2 |= (1 << (15 - bit))
else:
byte3 |= (1 << (23 - bit))
commands.append(bytes([byte1, byte2, byte3]))
commands.append(b'\n')
commands.append(f"\nURL: {TEST_URL}\n\n\n".encode('euc-kr'))
commands.append(GS + b'V' + bytes([1]))
return b''.join(commands)
def method_3_native_qr_simple():
"""방법 3: 내장 QR (더 간단한 설정)"""
ESC = b'\x1b'
GS = b'\x1d'
commands = []
commands.append(ESC + b'@')
commands.append("\n================================\n".encode('euc-kr'))
commands.append(" *** 방법 3 ***\n".encode('euc-kr'))
commands.append(" 내장 QR 간단 설정\n".encode('euc-kr'))
commands.append("================================\n\n".encode('euc-kr'))
qr_data = TEST_URL.encode('utf-8')
data_len = len(qr_data) + 3
# Model 2
commands.append(GS + b'(k' + bytes([3, 0, 49, 65, 50]))
# Error correction L
commands.append(GS + b'(k' + bytes([3, 0, 49, 69, 48]))
# Size 4
commands.append(GS + b'(k' + bytes([3, 0, 49, 67, 4]))
# Store data
commands.append(GS + b'(k' + bytes([data_len & 0xFF, (data_len >> 8) & 0xFF, 49, 80, 48]) + qr_data)
# Print
commands.append(GS + b'(k' + bytes([3, 0, 49, 81, 48]))
commands.append(f"\n\nURL: {TEST_URL}\n\n\n".encode('euc-kr'))
commands.append(GS + b'V' + bytes([1]))
return b''.join(commands)
def method_4_native_qr_model1():
"""방법 4: 내장 QR Model 1 (구형)"""
ESC = b'\x1b'
GS = b'\x1d'
commands = []
commands.append(ESC + b'@')
commands.append("\n================================\n".encode('euc-kr'))
commands.append(" *** 방법 4 ***\n".encode('euc-kr'))
commands.append(" 내장 QR Model 1\n".encode('euc-kr'))
commands.append("================================\n\n".encode('euc-kr'))
qr_data = TEST_URL.encode('utf-8')
data_len = len(qr_data) + 3
# Model 1 (n=49)
commands.append(GS + b'(k' + bytes([3, 0, 49, 65, 49]))
# Error correction L
commands.append(GS + b'(k' + bytes([3, 0, 49, 69, 48]))
# Size 4
commands.append(GS + b'(k' + bytes([3, 0, 49, 67, 4]))
# Store data
commands.append(GS + b'(k' + bytes([data_len & 0xFF, (data_len >> 8) & 0xFF, 49, 80, 48]) + qr_data)
# Print
commands.append(GS + b'(k' + bytes([3, 0, 49, 81, 48]))
commands.append(f"\n\nURL: {TEST_URL}\n\n\n".encode('euc-kr'))
commands.append(GS + b'V' + bytes([1]))
return b''.join(commands)
def method_5_raster_tiny():
"""방법 5: Raster 초소형 (40x40)"""
ESC = b'\x1b'
GS = b'\x1d'
commands = []
commands.append(ESC + b'@')
commands.append("\n================================\n".encode('euc-kr'))
commands.append(" *** 방법 5 ***\n".encode('euc-kr'))
commands.append(" Raster 40x40 (GS v 0)\n".encode('euc-kr'))
commands.append("================================\n\n".encode('euc-kr'))
# 40x40 QR
qr = qrcode.QRCode(version=1, box_size=1, border=1)
qr.add_data(TEST_URL)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white").resize((40, 40)).convert('1')
width, height = img.size
pixels = img.load()
width_bytes = (width + 7) // 8
commands.append(GS + b'v0' + bytes([0]))
commands.append(bytes([width_bytes & 0xFF, (width_bytes >> 8) & 0xFF]))
commands.append(bytes([height & 0xFF, (height >> 8) & 0xFF]))
for y in range(height):
for x in range(0, width, 8):
byte = 0
for bit in range(8):
if x + bit < width and pixels[x + bit, y] == 0:
byte |= (1 << (7 - bit))
commands.append(bytes([byte]))
commands.append(f"\n\nURL: {TEST_URL}\n\n\n".encode('euc-kr'))
commands.append(GS + b'V' + bytes([1]))
return b''.join(commands)
def method_6_no_align():
"""방법 6: 정렬 없이 + 작은 QR"""
ESC = b'\x1b'
GS = b'\x1d'
commands = []
commands.append(ESC + b'@')
# 정렬 명령 없음!
commands.append("\n================================\n".encode('euc-kr'))
commands.append(" *** 방법 6 ***\n".encode('euc-kr'))
commands.append(" 정렬 없음 + QR 35x35\n".encode('euc-kr'))
commands.append("================================\n\n".encode('euc-kr'))
# 35x35 QR
qr = qrcode.QRCode(version=1, box_size=1, border=1)
qr.add_data(TEST_URL)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white").resize((35, 35)).convert('1')
width, height = img.size
pixels = img.load()
# ESC * m=1 (8-dot double-density)
for y in range(0, height, 8):
commands.append(ESC + b'*' + bytes([1, width & 0xFF, (width >> 8) & 0xFF]))
for x in range(width):
byte = 0
for bit in range(min(8, height - y)):
if pixels[x, y + bit] == 0:
byte |= (1 << (7 - bit))
commands.append(bytes([byte]))
commands.append(b'\n')
commands.append(f"\nURL: {TEST_URL}\n\n\n".encode('euc-kr'))
commands.append(GS + b'V' + bytes([1]))
return b''.join(commands)
def main():
print("="*60)
print("ESC/POS QR 테스트 v2 - 더 많은 변형")
print("="*60)
print(f"프린터: {PRINTER_IP}:{PRINTER_PORT}")
print(f"테스트 URL: {TEST_URL}")
print("="*60)
methods = [
("방법 1: 30x30 ESC * m=0", method_1_tiny_qr_escstar),
("방법 2: 50x50 ESC * m=32", method_2_medium_qr_escstar_mode32),
("방법 3: 내장 QR 간단", method_3_native_qr_simple),
("방법 4: 내장 QR Model 1", method_4_native_qr_model1),
("방법 5: 40x40 Raster", method_5_raster_tiny),
("방법 6: 정렬 없음 35x35", method_6_no_align),
]
results = []
for name, method_func in methods:
try:
data = method_func()
success = send_to_printer(data, name)
results.append((name, success))
except Exception as e:
print(f"[{name}] ❌ 오류: {e}")
results.append((name, False))
print("\n" + "="*60)
print("결과 요약")
print("="*60)
for name, success in results:
print(f"{name}: {'' if success else ''}")
print("\n6장의 영수증이 나옵니다. QR이 보이는 번호를 알려주세요!")
print("="*60)
if __name__ == "__main__":
main()