fix: ESC/POS QR 인쇄 호환성 개선 (ESC * 방식)
- QR 크기 축소: 150x150px → 100x100px (안정성 향상) - ESC * 명령어 사용 (24-dot double-density) - 더 많은 프린터 지원 - image_to_raster_esc_star() 함수 추가 - 디버깅 로그 추가 (각 단계 print) - QR 비트맵 실패 시 URL 텍스트로 폴백 GS v 0 방식은 일부 프린터에서 미지원 → ESC * 방식으로 변경 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2ec73dd73d
commit
3413211c49
@ -27,17 +27,17 @@ def print_qr_receipt_escpos(qr_url, transaction_id, total_amount,
|
||||
"""
|
||||
|
||||
try:
|
||||
# 1. QR 코드 이미지 생성 (150x150px)
|
||||
qr = qrcode.QRCode(version=1, box_size=5, border=2)
|
||||
print(f"[ESC/POS] QR 인쇄 시작: {qr_url}")
|
||||
|
||||
# 1. QR 코드 이미지 생성 (작게: 100x100px)
|
||||
qr = qrcode.QRCode(version=1, box_size=3, border=2)
|
||||
qr.add_data(qr_url)
|
||||
qr.make(fit=True)
|
||||
qr_image = qr.make_image(fill_color="black", back_color="white")
|
||||
qr_image = qr_image.resize((150, 150))
|
||||
qr_image = qr_image.resize((100, 100))
|
||||
print(f"[ESC/POS] QR 이미지 생성 완료: 100x100px")
|
||||
|
||||
# 2. QR 이미지를 ESC/POS 비트맵으로 변환
|
||||
qr_bitmap = image_to_raster(qr_image)
|
||||
|
||||
# 3. ESC/POS 명령어 조립
|
||||
# 2. ESC/POS 명령어 조립
|
||||
ESC = b'\x1b'
|
||||
GS = b'\x1d'
|
||||
|
||||
@ -67,11 +67,20 @@ def print_qr_receipt_escpos(qr_url, transaction_id, total_amount,
|
||||
commands.append("================================\n".encode('euc-kr'))
|
||||
commands.append("\n".encode('euc-kr'))
|
||||
|
||||
# QR 코드 인쇄
|
||||
commands.append(qr_bitmap) # QR 비트맵 데이터
|
||||
commands.append("\n".encode('euc-kr'))
|
||||
# 3. QR 코드 인쇄 (ESC * 방식 - 더 호환성 높음)
|
||||
try:
|
||||
qr_bitmap = image_to_raster_esc_star(qr_image)
|
||||
commands.append(qr_bitmap)
|
||||
commands.append(b"\n")
|
||||
print(f"[ESC/POS] QR 비트맵 변환 완료 (ESC *)")
|
||||
except Exception as e:
|
||||
print(f"[ESC/POS] QR 비트맵 변환 실패: {e}")
|
||||
# QR 실패 시 URL 텍스트로 대체
|
||||
commands.append("QR 코드:\n".encode('euc-kr'))
|
||||
commands.append(f"{qr_url}\n".encode('euc-kr'))
|
||||
|
||||
# 안내 문구
|
||||
commands.append("\n".encode('euc-kr'))
|
||||
commands.append(ESC + b'!\x08') # 작게
|
||||
commands.append("QR 촬영하고 포인트 받으세요!\n".encode('euc-kr'))
|
||||
commands.append(ESC + b'!\x00') # 보통
|
||||
@ -100,6 +109,67 @@ def print_qr_receipt_escpos(qr_url, transaction_id, total_amount,
|
||||
return False
|
||||
|
||||
|
||||
def image_to_raster_esc_star(image):
|
||||
"""
|
||||
PIL 이미지를 ESC/POS 비트맵으로 변환 (ESC * 방식 - 호환성 높음)
|
||||
|
||||
ESC * m nL nH d1...dk 명령어 사용
|
||||
m=33 (24-dot double-density)
|
||||
|
||||
Args:
|
||||
image (PIL.Image): PIL 이미지 객체
|
||||
|
||||
Returns:
|
||||
bytes: ESC/POS 비트맵 명령어
|
||||
"""
|
||||
# 이미지를 흑백으로 변환
|
||||
image = image.convert('1') # 1-bit 흑백
|
||||
width, height = image.size
|
||||
|
||||
# 픽셀 데이터 가져오기
|
||||
pixels = image.load()
|
||||
|
||||
# ESC * 명령어로 라인별 인쇄 (24-dot 방식)
|
||||
ESC = b'\x1b'
|
||||
commands = []
|
||||
|
||||
# 24픽셀(3바이트) 단위로 인쇄
|
||||
for y in range(0, height, 24):
|
||||
# 현재 라인의 높이 (최대 24픽셀)
|
||||
line_height = min(24, height - y)
|
||||
|
||||
# 너비 바이트 수
|
||||
width_bytes = (width + 7) // 8
|
||||
|
||||
# ESC * m nL nH: m=33 (24-dot double-density)
|
||||
nL = width & 0xFF
|
||||
nH = (width >> 8) & 0xFF
|
||||
commands.append(ESC + b'*' + bytes([33, nL, nH]))
|
||||
|
||||
# 라인 데이터 생성
|
||||
for x in range(width):
|
||||
# 세로 24픽셀을 3바이트로 변환
|
||||
byte1, byte2, byte3 = 0, 0, 0
|
||||
|
||||
for bit in range(line_height):
|
||||
pixel_y = y + bit
|
||||
if pixel_y < height:
|
||||
if pixels[x, pixel_y] == 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')
|
||||
|
||||
return b''.join(commands)
|
||||
|
||||
|
||||
def image_to_raster(image):
|
||||
"""
|
||||
PIL 이미지를 ESC/POS 비트맵 래스터 데이터로 변환
|
||||
|
||||
Loading…
Reference in New Issue
Block a user