https://link.coupang.com/a/cP09xt
LG전자 2025 그램 Pro AI 16 WQXGA Ultra5 루나레이크 - 노트북 | 쿠팡
쿠팡에서 LG전자 2025 그램 Pro AI 16 WQXGA Ultra5 루나레이크 구매하고 더 많은 혜택을 받으세요! 지금 할인중인 다른 노트북 제품도 바로 쿠팡에서 확인할 수 있습니다.
www.coupang.com

저는 여태껏 pdf는 글자가 깨지는 일이 없을거라 생각했는데
인쇄를 위해 중국쪽 업체에 보냈더니
아래 이미지처럼 글자가 깨지더라구요.

이를 방지하는 작업을 ‘아웃라인
(글자를 벡터 도형으로 바꿔 폰트 미설치·
대체로 인한 깨짐을 방지)’이라고 합니다.
문제는 이렇게 해도 표 안에 있는 글자의 경우에는
아웃라인이 적용되지 않는 경우가 생겨요.
아웃라인이 제대로 적용되었는지
최종 테스트 하는 방법이 있습니다.
PitStop Pro 또는 callas pdfToolbox를 사용할 수도 있지만
이 경우에는 어도비 프로에 유료 사용자에게만 제공해요.
무료로 검사하고자 하는 경우에는 파이썬으로 쉽게 할 수 있어요.
아래의 모듈을 설치해주고
pip install pypdf pdfminer.six pymupdf
아래의 코드를 활용하면 되구요.
# check_outline.py
# 대상 파일: C:\Windows\System32\test.pdf
import sys
from dataclasses import dataclass
from typing import List
from pypdf import PdfReader
from pypdf.generic import ContentStream
from pdfminer.high_level import extract_text
import fitz # PyMuPDF
PDF_PATH = r"C:\Windows\System32\test.pdf"
@dataclass
class PageReport:
page_index: int
has_text_ops: bool
bt_blocks: int
font_resources: bool
mined_chars: int
drawings: int
verdict: str
def _pypdf_text_signals(reader: PdfReader, page_obj):
has_text_ops = False
bt_blocks = 0
font_resources = False
try:
res = page_obj.get("/Resources")
if res and res.get("/Font"):
font_resources = True
except Exception:
pass
try:
contents = page_obj.get_contents()
if contents is not None:
cs = ContentStream(contents, reader)
for operands, op in cs.operations:
op = op if isinstance(op, bytes) else bytes(op, "latin1")
if op == b"BT":
bt_blocks += 1
if op in (b"Tj", b"TJ", b"'", b'"'):
has_text_ops = True
except Exception:
pass
return has_text_ops, bt_blocks, font_resources
def _pdfminer_char_count(pdf_path: str, page_index: int) -> int:
try:
txt = extract_text(pdf_path, page_numbers=[page_index])
return len(txt.strip()) if txt else 0
except Exception:
return 0
def _pymupdf_drawings(doc: fitz.Document, page_index: int) -> int:
try:
p = doc.load_page(page_index)
return len(p.get_drawings())
except Exception:
return 0
def analyze_pdf(pdf_path: str) -> List[PageReport]:
reader = PdfReader(pdf_path)
doc = fitz.open(pdf_path)
reports: List[PageReport] = []
for i, page in enumerate(reader.pages):
has_text_ops, bt_blocks, font_resources = _pypdf_text_signals(reader, page)
mined_chars = _pdfminer_char_count(pdf_path, i)
drawings = _pymupdf_drawings(doc, i)
if (not has_text_ops) and mined_chars == 0:
verdict = "텍스트 없음(아웃라인/이미지 가능성 높음)" if not font_resources \
else "텍스트 미표시 추정(아웃라인 또는 비표준 텍스트)"
else:
verdict = "실제 텍스트 있음(완전 아웃라인 아님)"
reports.append(PageReport(
page_index=i + 1,
has_text_ops=has_text_ops,
bt_blocks=bt_blocks,
font_resources=font_resources,
mined_chars=mined_chars,
drawings=drawings,
verdict=verdict
))
doc.close()
return reports
def print_summary(reports: List[PageReport]):
total = len(reports)
no_text_pages = sum(1 for r in reports if "텍스트 없음" in r.verdict)
print("페이지별 결과")
for r in reports:
print(f"- p{r.page_index:>3}: "
f"text_ops={r.has_text_ops}, BT={r.bt_blocks}, fonts={r.font_resources}, "
f"chars(pdfminer)={r.mined_chars}, drawings={r.drawings} -> {r.verdict}")
print("\n요약")
if no_text_pages == total:
print(f"전체 {total}쪽 모두 텍스트 없음 → 전면 아웃라인/이미지 PDF 추정")
elif no_text_pages == 0:
print(f"전체 {total}쪽 모두 텍스트 존재 → 아웃라인 처리되지 않음")
else:
print(f"혼합: 텍스트 없는 페이지 {no_text_pages}/{total}쪽 → 일부 페이지만 아웃라인/이미지")
if __name__ == "__main__":
# 고정 경로 검사. 필요 시 다른 파일을 인수로 받아도 됩니다.
path = PDF_PATH if len(sys.argv) < 2 else sys.argv[1]
reports = analyze_pdf(path)
print_summary(reports)
이때 내가 점검할 pdf의 경로와 파일명을 아래와 같이 수정해주면 됩니다.
PDF_PATH = r"C:\Windows\System32\cata2.pdf"
정상이라면 이렇게 결과 요약이 나와요.

아웃라인이 제대로 되지 않은 경우
‘실제 텍스트 있음’이라고 알려주고,
몇 페이지가 문제인지도 알려줍니다.

파이썬에 대한 기본 지식 문법 없이도
생성형AI가 코드 다 짜줬어요.
완전 신세계입니다.
#PDF #아웃라인 #폰트아웃라인 #글자깨짐 #인쇄전검사 #프리플라이트 #프리프레스 #폰트임베딩 #텍스트아웃라인 #표텍스트 #무료점검 #파이썬 #pypdf #pdfminer #PyMuPDF #fitz #PDF검사 #PDF체크 #인쇄소오류예방 #CJK폰트 #한글폰트 #벡터화 #PitStop대체 #pdfToolbox대체 #AdobeAcrobat #자동화 #워크플로우 #디자인가이드 #출력오류해결 #튜토리얼
'파이썬' 카테고리의 다른 글
ai파일 pdf변환 후 하나로 합치기(파이썬 활용) (0) | 2025.09.11 |
---|---|
파이썬 문법 쉽게 이해하기: 클로저(Closure)와 데코레이터(Decorator) (3) | 2025.08.26 |
[파이썬 문법] return(반환)과 print(출력)의 차이점 (2) | 2025.06.24 |
파이썬 클래스와 객체, 진짜 쉽게 이해하기! (0) | 2025.04.29 |
파이썬 딕셔너리, value 기준 내림차순 정렬하는 방법 (0) | 2025.04.29 |