728x90
들어가며
지난 글에서는 EPSON 써멀 프린터 라이브러리의 각 연결 방식별 구현에 대해 살펴보았습니다. 이번 글에서는 프린터의 핵심 출력 기능인 텍스트, 바코드, QR 코드, 이미지 출력 기능의 구현을 상세히 분석해보겠습니다.
프린터의 출력 기능은 크게 두 가지 계층으로 구현되어 있습니다:
PrinterDialect
: 각 기능별 바이트 코드 생성T83PrinterAdaptor
: 생성된 바이트 코드를 실제 프린터로 전송
이러한 계층 구조는 명령어 생성과 전송을 분리하여 유지보수성과 확장성을 높여줍니다.
1. 텍스트 출력 구현
PrinterDialect의 텍스트 관련 명령어
object PrinterDialect {
private val FONT_SIZE_CMD: ByteArray = byteArrayOf(GS, '!'.code.toByte())
private val REVERSE_WB_CMD: ByteArray = byteArrayOf(GS, 'B'.code.toByte())
private val FONT_EMPHASIZE_CMD: ByteArray = byteArrayOf(ESC, 'E'.code.toByte())
private val FONT_UNDERLINE_CMD: ByteArray = byteArrayOf(ESC, '-'.code.toByte())
private val ALIGNMENT_CMD: ByteArray = byteArrayOf(ESC, 'a'.code.toByte())
internal fun createFontSizeCode(width: Int = 0, height: Int = 0): ByteArray =
FONT_SIZE_CMD + byteArrayOf((height + width).toByte())
internal fun createFontReverseWbCode(flag: Int = OFF_FLAG): ByteArray =
REVERSE_WB_CMD + byteArrayOf(flag.toByte())
internal fun createFontEmphasizeCode(flag: Int = OFF_FLAG): ByteArray =
FONT_EMPHASIZE_CMD + byteArrayOf(flag.toByte())
internal fun createFontUnderlineCode(flag: Int = OFF_FLAG): ByteArray =
FONT_UNDERLINE_CMD + byteArrayOf(flag.toByte())
}
텍스트 출력과 관련된 모든 명령어는 PrinterDialect
에 정의되어 있습니다. 각 명령어는:
- 글자 크기 조절
- 반전 효과
- 강조(볼드) 효과
- 밑줄 효과
- 정렬
등의 기능을 제공합니다.
T83PrinterAdaptor의 텍스트 출력 구현
abstract class T83PrinterAdaptor : EpsonPrinterAdaptor {
internal fun printText(
data: String,
alignment: Alignment,
options: Set<TextStyle>,
textHeight: Int,
textWidth: Int
) {
outputWithResetStyle(
PrinterDialect.createAlignmentCode(alignment.code)
+ options.map { it.code }.flatMap { it.toList() }.toByteArray()
+ TextSize(textWidth, textHeight).code
+ data.toEucKrByteArray()
)
}
}
텍스트 출력 구현의 특징:
- 스타일 초기화 후 출력
- EUC-KR 인코딩을 사용한 한글 지원
- TextSize 클래스를 통한 크기 유효성 검사
2. 바코드 출력 구현
PrinterDialect의 바코드 관련 명령어
object PrinterDialect {
private val PRINT_BARCODE_CMD: ByteArray = byteArrayOf(GS, 'k'.code.toByte())
private val BARCODE_HEIGHT_CMD: ByteArray = byteArrayOf(GS, 'h'.code.toByte())
private val BARCODE_WIDTH_CMD: ByteArray = byteArrayOf(GS, 'w'.code.toByte())
private val BARCODE_HRI_CMD: ByteArray = byteArrayOf(GS, 'H'.code.toByte())
internal fun createPrintCode128Code(data: String, d2: Code128CodeSet = Code128CodeSet.A): ByteArray {
val m = 73
val d1 = 123
val parameter = byteArrayOf(d1.toByte(), d2.code.toByte()) + data.toEucKrByteArray()
val n = parameter.size
return PRINT_BARCODE_CMD + byteArrayOf(m.toByte(), n.toByte()) + parameter
}
}
바코드 출력은:
- 바코드 높이/너비 설정
- HRI(Human Readable Interpretation) 위치 설정
- 다양한 바코드 타입(CODE128, ITF, EAN8 등) 지원
BarcodeSize 밸류 오브젝트를 통한 크기 제어
internal class BarcodeWidth(private val size: Int) {
init {
require(
size / BARCODE_WIDTH_CORRECTION_VALUE
in BARCODE_WIDTH_MIN..BARCODE_WIDTH_MAX
)
{
"TM-T83III는 바코드 가로 길이를 ${BARCODE_WIDTH_MIN * BARCODE_WIDTH_CORRECTION_VALUE}과 " +
"${BARCODE_WIDTH_MAX * BARCODE_WIDTH_CORRECTION_VALUE}만 지원합니다."
}
}
internal val code: ByteArray
get() = PrinterDialect.createBarcodeWidthCode(size / BARCODE_WIDTH_CORRECTION_VALUE)
}
BarcodeSize 클래스의 특징:
- 크기 유효성 검사
- 프린터 모델별 제약사항 반영
- 보정값을 통한 실제 출력 크기 조정
3. QR 코드 출력 구현
PrinterDialect의 QR 코드 관련 명령어
object PrinterDialect {
private val QR_CODE_CMD: ByteArray = byteArrayOf(GS, '('.code.toByte(), 'k'.code.toByte())
internal fun createSelectQrCodeModelCode(): ByteArray {
val cn: Byte = 49
val parameter = byteArrayOf(cn, SELECT_QR_MODEL_FN, QR_MODEL_NO, n2)
val plPh = parameter.plPh
return QR_CODE_CMD + plPh + parameter
}
internal fun createQrCodeSizeCode(size: Int = 5): ByteArray {
val cn: Byte = 49
val parameter = byteArrayOf(cn, QR_SIZE_FN, size.toByte())
val plPh = parameter.plPh
return QR_CODE_CMD + plPh + parameter
}
}
QR 코드 출력의 특징:
- QR 코드 모델 선택
- 크기 설정
- 오류 정정 레벨 설정
- 데이터 저장 및 출력 명령 분리
QR 코드 크기 관리
internal fun Int.toQrModuleSize() =
(this * PrinterDialect.QR_SIZE_RATIO).toInt()
.coerceIn(
PrinterDialect.QR_MODULE_SIZE_MIN,
PrinterDialect.QR_MODULE_SIZE_MAX
)
internal fun Pair<Int, Int>.pickNonDefault(): Int {
return if (this.first == this.second) {
this.first
} else {
if (this.first.isNotQrSizeDefault()) {
if (this.second.isNotQrSizeDefault()) {
max(this.first, this.second)
} else {
this.first
}
} else {
this.second
}
}
}
QR 코드 크기 관리의 특징:
- 모듈 사이즈 자동 계산
- 가로/세로 크기 자동 조정
- 기본값 처리 로직
4. 이미지 출력 구현
이미지 처리 과정
internal fun BufferedImage.toDitheredBitmapData(): ByteArray {
return this.toGrayScale().toDitheredData().toBitmapData()
}
private fun BufferedImage.toGrayScale(): Array<IntArray> {
//..grayScale 연산 코드.
return grayScale
}
이미지 출력 구현의 특징:
- 그레이스케일 변환
- 디더링(Dithering) 처리
- 비트맵 데이터 변환
출력 기능별 특징 비교
1. 텍스트 출력
- EUC-KR 인코딩으로 한글 지원
- 다양한 스타일 옵션
- 크기 조절의 유연성
2. 바코드 출력
- 다양한 바코드 타입 지원
- 크기 제약 조건 관리
- HRI 위치 설정 기능
3. QR 코드 출력
- 자동 크기 조정
- 오류 정정 레벨 설정
- 효율적인 데이터 처리
4. 이미지 출력
- 그레이스케일 처리
- 디더링을 통한 품질 개선
마치며
프린터의 각 출력 기능은 명령어 생성(PrinterDialect
)과 실제 출력(T83PrinterAdaptor
) 계층이 분리되어 있어, 아래와 같은 이점을 얻을 수 있었습니다.
- 새로운 연결 방식 별 독립적인 개발시 명령어 셋 재사용 가능
- 새로운 출력 기능 추가가 용이
- 프린터 모델별 제약사항 관리가 편리
다음 글에서는 프린터 상태 관리와 예외 처리에 대해 자세히 살펴보도록 하겠습니다.
728x90