두 번째 앱 출시기 1 — 스캔과 이미지 변환이 같은 글자층을 쓰도록
스캔본은 페이지를 채우고 불러온 사진은 여백 안에 놓입니다. 두 경로에서 따로 계산하던 OCR 좌표를 InvisibleTextLayer로 모으며, 각 변환기에 남길 일을 정했습니다.
들어가며
물타기 계산기를 Play 테스트 트랙에 올린 뒤 Pocket PDF를 만들기 시작했습니다. 카메라로 찍거나 불러온 문서를 PDF로 묶고, 사진 속 글자도 검색하고 복사할 수 있게 만드는 앱입니다.
스캔과 이미지 변환에는 같은 기능이 필요했습니다. 사진 위에 OCR이 읽은 글자를 보이지 않게 얹는 일입니다. 그런데 두 경로의 좌표 계산이 따로 있었습니다. 이미지 변환에 글자층을 붙이면서, 스캔 쪽의 SearchablePdfBuilder에서 이 계산을 꺼냈습니다.
같은 글자를 다른 자리에 얹기
스캔본은 PDF 페이지를 가득 채웁니다. 이미지 변환에서는 사진을 여백 안에 가운데 배치합니다. 그림의 위치와 크기는 달라도, OCR이 읽은 글자를 그림의 같은 자리에 놓는 계산은 같습니다.
ML Kit에서 받은 문자열과 바운딩 박스는 이미지의 픽셀 좌표를 사용합니다. 이를 PDF의 포인트 좌표로 바꾸고, 위에서부터 재는 이미지 좌표를 아래에서부터 재는 PDF 좌표에 맞춥니다.
이미지를 페이지 어디에 얼마나 크게 놓을지는 각 변환기가 정합니다. InvisibleTextLayer에는 그 위치와 크기를 넘겨, 글자도 같은 비율로 옮기게 했습니다. 스캔인지 이미지 변환인지에 따라 좌표 계산을 따로 고칠 필요가 없어졌습니다.
글자는 RenderingMode.NEITHER로 그려 화면에서는 보이지 않게 했습니다. 사진은 그대로 보이고, PDF 안에는 선택하거나 검색할 문자열이 들어갑니다.
옮기는 중에 폰트도 바꿨습니다
코드를 옮기면서 sanitize를 다시 읽다가 한글을 공백으로 바꾸는 조건을 발견했습니다. 기존 Helvetica 폰트가 처리하지 못하는 문자를 지우고 있었습니다. 이 문제를 확인한 과정은 한글이 사라진 PDF 글자층에 남겼습니다.
한글 폰트를 넣는 수정도 공통 구현에 적용했습니다. 두 변환기는 같은 폰트를 글자층에 넘기고, 새 폰트를 사용할 때는 한글을 지우는 필터를 거치지 않습니다. 폰트 변환과 PDF 검증은 별도 글에서 다룹니다.
마치며
이번에 두 경로를 합쳐 둔 덕분에 한글 처리도 함께 고칠 수 있었습니다. 각 변환기에는 페이지 안에서 사진의 자리를 정하는 일이 남았습니다.