PDF/X 인쇄 제작
PDF/X(ISO 15930)는 인쇄용 PDF 파일을 안정적으로 교환하기 위한 표준입니다. PDF Oxide는 모든 주요 PDF/X 레벨을 검증하며, 페이지 박스, 색 공간, 투명도, ICC 프로파일, 출력 인텐트를 확인합니다.
바인딩 지원 범위. PDF/X 검증은 Python(
doc.validate_pdf_x(level)), Rust(validate_pdf_x+PdfXValidator빌더), Go(doc.ValidatePdfX(level))에서 제공됩니다. WASM과 **C#**은 아직 PDF/X 검증을 노출하지 않습니다. Rust CLI(pdf-oxide validate --pdfx 4 doc.pdf)를 사용하거나 지원되는 바인딩 중 하나를 통해 호출하세요.
지원 레벨
| 레벨 | 표준 | 투명도 | RGB | 레이어 | 외부 ICC | 외부 그래픽 |
|---|---|---|---|---|---|---|
| X-1a:2001 | ISO 15930-1 | 불가 | 불가 | 불가 | 불가 | 불가 |
| X-1a:2003 | ISO 15930-4 | 불가 | 불가 | 불가 | 불가 | 불가 |
| X-3:2002 | ISO 15930-3 | 불가 | 가능 | 불가 | 불가 | 불가 |
| X-3:2003 | ISO 15930-6 | 불가 | 가능 | 불가 | 불가 | 불가 |
| X-4 | ISO 15930-7 | 가능 | 가능 | 가능 | 불가 | 불가 |
| X-4p | ISO 15930-7 | 가능 | 가능 | 가능 | 가능 | 불가 |
| X-5g | ISO 15930-8 | 가능 | 가능 | 가능 | 불가 | 가능 |
| X-5n | ISO 15930-8 | 가능 | 가능 | 가능 | 불가 | 가능 |
| X-5pg | ISO 15930-8 | 가능 | 가능 | 가능 | 가능 | 가능 |
| X-6 | ISO 15930-9 | 가능 | 가능 | 가능 | 불가 | 불가 |
| X-6n | ISO 15930-9 | 가능 | 가능 | 가능 | 불가 | 가능 |
| X-6p | ISO 15930-9 | 가능 | 가능 | 가능 | 가능 | 불가 |
PDF/X-1a는 가장 엄격합니다. CMYK만 허용되며 투명도와 레이어는 사용할 수 없습니다. PDF/X-4는 가장 널리 사용되는 현대적인 레벨로, ICC 프로파일을 포함한 투명도와 RGB를 허용합니다.
빠른 검증
from pdf_oxide import PdfDocument
doc = PdfDocument("document.pdf")
result = doc.validate_pdf_x("4")
print(f"Valid: {result.valid}")
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::pdf_x::{validate_pdf_x, PdfXLevel};
let mut doc = PdfDocument::open("print-ready.pdf")?;
let result = validate_pdf_x(&mut doc, PdfXLevel::X4)?;
if result.has_errors() {
println!("Not PDF/X-4 compliant ({} errors):", result.errors.len());
for error in &result.errors {
println!(" [{}] {} (clause {})",
error.code, error.message,
error.clause.as_deref().unwrap_or("n/a"));
}
} else {
println!("Document is PDF/X-4 compliant");
}
doc, _ := pdfoxide.Open("print-ready.pdf")
defer doc.Close()
// Level encoding: 0 = X-1a:2001, 1 = X-1a:2003, 2 = X-3:2002, 3 = X-3:2003, 4 = X-4, ...
valid, errs, err := doc.ValidatePdfX(4) // PDF/X-4
if err != nil { log.Fatal(err) }
if valid {
fmt.Println("Document is PDF/X-4 compliant")
} else {
fmt.Printf("Not PDF/X-4 compliant (%d errors):\n", len(errs))
for _, e := range errs {
fmt.Printf(" %s\n", e)
}
}
검증기 API
PdfXValidator 빌더는 검증 실행 방식을 구성합니다.
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::pdf_x::{PdfXValidator, PdfXLevel};
let mut doc = PdfDocument::open("artwork.pdf")?;
let result = PdfXValidator::new(PdfXLevel::X1a2001)
.stop_on_first_error(false)
.include_warnings(true)
.validate(&mut doc)?;
println!("Errors: {}", result.errors.len());
println!("Warnings: {}", result.warnings.len());
println!("Total issues: {}", result.total_issues());
검사 항목
XMP 식별
검증기는 XMP 메타데이터가 올바른 PDF/X 버전을 선언하는지 확인합니다.
pdfxid:GTS_PDFXVersion이 대상 레벨과 일치해야 합니다- 선언된 버전은 대상 레벨의
gts_pdfx_version()과 비교됩니다
페이지 박스 관계
PDF/X는 페이지 박스의 특정 중첩 구조를 요구합니다.
TrimBox <= BleedBox <= MediaBox
ArtBox <= MediaBox
검증기는 모든 페이지에 대해 다음을 확인합니다.
- TrimBox가 존재함(모든 PDF/X 레벨에서 필수)
- TrimBox가 BleedBox 안에 포함됨(BleedBox가 정의된 경우)
- BleedBox가 MediaBox 안에 포함됨
- ArtBox가 MediaBox 안에 포함됨(ArtBox가 정의된 경우)
- 부동소수점 반올림을 위한 0.01 포인트의 허용 오차
투명도 감지
PDF/X-1a와 PDF/X-3에서는 투명도가 허용되지 않습니다. 검증기는 다음을 확인합니다.
- ExtGState 사전의 SMask(
/None이거나 없어야 함) - CA(선 불투명도)가 1.0이어야 함
- ca(채우기 불투명도)가 1.0이어야 함
- BM(블렌드 모드)가
Normal또는Compatible이어야 함
PDF/X-4 이상의 레벨은 투명도를 허용합니다.
색 공간 검증
검증기는 장치 종속 색상의 사용을 확인합니다.
- DeviceRGB는 PDF/X-1a에서 허용되지 않습니다(CMYK 전용)
- 출력 인텐트 없이 사용된 DeviceRGB, DeviceCMYK, DeviceGray는 더 엄격한 레벨에서 오류를 발생시킵니다
- 페이지 콘텐츠 스트림의 색상 연산자
rg,RG,k,K,g,G를 스캔합니다
ICC 프로파일 검증
ICCBased 색 공간에 대해 검증기는 다음을 확인합니다.
- 프로파일 스트림에 필수
/N(컴포넌트 수) 항목이 포함됨 /N값이 예상되는 색 공간 차원과 일치함(그레이는 1, RGB는 3, CMYK는 4)- 프로파일 데이터가 존재하며 비어 있지 않음
출력 인텐트
PDF/X는 의도된 인쇄 조건을 설명하는 출력 인텐트를 요구합니다.
- 문서 카탈로그에
/OutputIntents배열이 있어야 합니다 - 서브타입이
GTS_PDFX인 항목이 최소 하나 필요합니다 - 출력 인텐트는 ICC 프로파일 또는 등록된 인쇄 조건을 참조해야 합니다
XValidationResult
pub struct XValidationResult {
pub level: PdfXLevel,
pub errors: Vec<XComplianceError>,
pub warnings: Vec<XComplianceError>,
pub stats: XValidationStats,
}
XComplianceError
pub struct XComplianceError {
pub code: XErrorCode,
pub message: String,
pub severity: XSeverity,
pub page: Option<usize>,
pub object_id: Option<u32>,
pub clause: Option<String>,
}
오류에는 위반이 발견된 페이지 번호와 객체 ID가 포함되므로 소스 파일에서 문제를 손쉽게 찾아 수정할 수 있습니다.
XErrorCode 카테고리
XErrorCode 열거형에는 카테고리별로 정리된 40개 이상의 구체적인 오류 코드가 포함되어 있습니다.
메타데이터: MissingOutputIntent, InvalidGtsPdfxVersion, MissingXmpIdentification
페이지 박스: MissingTrimBox, TrimBoxOutsideBleedBox, BleedBoxOutsideMediaBox, ArtBoxOutsideMediaBox
투명도: TransparencyNotAllowed, InvalidBlendMode, InvalidSMask, InvalidOpacity
색상: DeviceRgbNotAllowed, DeviceDependentColorWithoutIntent, InvalidIccProfile, MissingIccComponents
콘텐츠: ExternalContentNotAllowed, EncryptionNotAllowed, JavaScriptNotAllowed
PdfXLevel 메서드
| 메서드 | 반환 | 설명 |
|---|---|---|
iso_standard() |
&str |
ISO 표준 번호(예: "ISO 15930-7") |
required_pdf_version() |
&str |
최소 PDF 버전(예: "1.6") |
allows_transparency() |
bool |
투명도 그룹 허용 여부 |
allows_rgb() |
bool |
RGB 색 공간 허용 여부 |
allows_layers() |
bool |
선택적 콘텐츠 그룹 허용 여부 |
allows_external_icc() |
bool |
외부 ICC 프로파일 허용 여부 |
allows_external_graphics() |
bool |
외부 그래픽 참조 허용 여부 |
gts_pdfx_version() |
&str |
예상되는 GTS_PDFXVersion 값 |
xmp_version() |
&str |
예상되는 XMP 버전 식별자 |
from_gts_version(version) |
Option<Self> |
GTS 버전 문자열에서 레벨 파싱 |
실전 예제: 프리프레스 점검
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::pdf_x::{validate_pdf_x, PdfXLevel, XSeverity};
let mut doc = PdfDocument::open("magazine-cover.pdf")?;
let result = validate_pdf_x(&mut doc, PdfXLevel::X4)?;
println!("=== PDF/X-4 Prepress Report ===");
println!("Status: {}", if result.has_errors() { "REJECT" } else { "ACCEPT" });
// Group errors by severity
let critical: Vec<_> = result.errors.iter()
.filter(|e| e.is_error())
.collect();
let advisory: Vec<_> = result.warnings.iter().collect();
if !critical.is_empty() {
println!("\nCritical ({}):", critical.len());
for e in &critical {
let page_str = e.page
.map(|p| format!("page {}", p + 1))
.unwrap_or_else(|| "document".into());
println!(" [{}] {} ({})", e.code, e.message, page_str);
}
}
if !advisory.is_empty() {
println!("\nAdvisory ({}):", advisory.len());
for w in &advisory {
println!(" [{}] {}", w.code, w.message);
}
}
다음 단계
- PDF/A 검증 – 보존용 준수
- PDF/UA 접근성 – 접근성 검증
- API 레퍼런스 – 전체 Rust API