Task #614: export-png --dpi 옵션 — PNG pHYs chunk 메타데이터#734
Conversation
…-scale - PngExportOptions 에 dpi: Option<f64> 필드 추가 - --dpi <값> CLI 옵션 추가 (도움말 포함) - --scale 미지정 + --dpi 만 지정 시 scale = dpi / 96.0 자동 계산 - Skia PNG 인코딩 후 pHYs chunk 후처리 삽입 (IHDR 직후) - pHYs chunk: X/Y pixels-per-meter + unit=meter (PNG spec §11.3.5.3) - 단위 테스트: pHYs 삽입 위치 + PPM 값 + CRC32 검증 Closes edwardkim#614 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
export-png 명령에 --dpi <값> 옵션을 추가해, PNG 출력에 DPI 메타데이터를 pHYs chunk로 기록하여 인쇄 워크플로우에서 크기 힌트를 제공하는 변경입니다. 또한 --scale 미지정 시 scale = dpi / 96.0 자동 계산 로직이 렌더링 경로에 포함됩니다.
Changes:
export-pngCLI에--dpi옵션 추가 및 도움말/옵션 파싱 업데이트PngExportOptions에dpi: Option<f64>추가,--dpi만 지정 시 scale 자동 산출- Skia PNG 인코딩 결과 바이트에
pHYschunk를 삽입하는 후처리 및 CRC32 구현/테스트 추가
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/main.rs | --dpi 옵션 도움말/파싱 추가 및 PngExportOptions로 전달 |
| src/document_core/queries/rendering.rs | DPI→scale 자동 계산, PNG pHYs chunk 삽입 로직 및 CRC32/단위 테스트 추가 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let ppm = (dpi / 0.0254).round() as u32; | ||
| // PNG 구조: 8-byte signature + chunks (IHDR first, then others) | ||
| // 각 chunk: 4-byte length + 4-byte type + data + 4-byte CRC | ||
| if png.len() < 8 { | ||
| return png; | ||
| } | ||
| let mut pos = 8; // signature 이후 | ||
| // IHDR chunk 끝 위치 찾기 | ||
| if pos + 8 > png.len() { | ||
| return png; | ||
| } | ||
| let ihdr_len = u32::from_be_bytes([png[pos], png[pos + 1], png[pos + 2], png[pos + 3]]) as usize; | ||
| let ihdr_end = pos + 4 + 4 + ihdr_len + 4; // length + type + data + CRC |
| if png.len() < 8 { | ||
| return png; | ||
| } | ||
| let mut pos = 8; // signature 이후 |
| let png_bytes = SkiaLayerRenderer::new() | ||
| .with_font_paths(&options.font_paths) | ||
| .render_png_with_options(&layer_tree, raster_options) | ||
| .render_png_with_options(&layer_tree, raster_options)?; | ||
|
|
||
| if let Some(dpi) = options.dpi { | ||
| Ok(inject_png_phys(png_bytes, dpi)) | ||
| } else { | ||
| Ok(png_bytes) |
- PNG 시그니처 8바이트 검증 추가 - IHDR chunk 타입 (b"IHDR") 및 data length (=13) 검증 - ihdr_end 계산에 checked_add 사용 (오버플로우 방지) - 불필요한 mut 제거 (pos 변수) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Copilot 리뷰 피드백을 9758fab 에서 반영했습니다:
통합 테스트(export_options + dpi 경로)는 |
PR #734 (@oksure) 옵션 A 처리 — 2 commits cherry-pick + no-ff merge. 본질 정정 (2 files, +164/-5): - src/main.rs (+21/-1): CLI --dpi 옵션 파싱 + 도움말 갱신 + PngExportOptions 영역 dpi: Option<f64> 필드 추가 - src/document_core/queries/rendering.rs (+143/-4): · scale 결정 우선순위 갱신 — --dpi 만 지정 시 scale = dpi/96.0 자동 · inject_png_phys 후처리 함수 — PNG IHDR 직후 + 첫 IDAT 직전 영역 영역 pHYs chunk 삽입 (PNG spec §11.3.5.3) · CRC32 자체 구현 (외부 의존성 없음) · 신규 unit tests 2건: inject_png_phys_inserts_after_ihdr / png_crc32_known_value Copilot 리뷰 반영 (commit 9758fab): 방어 검증 강화 - PNG 시그니처 8바이트 검증 - IHDR chunk 타입 (b"IHDR") + data length (=13) 검증 - ihdr_end 계산 영역 checked_add (오버플로우 방지) - 불필요한 mut 제거 opt-in 영역 영역: - --dpi 미지정 시 기존 동작 100% 보존 - pHYs chunk 영역 영역 표준 PNG 메타데이터 (픽셀 데이터 무영향) 자기 검증: - cherry-pick 충돌 0건 - cargo build/test --release ✅ ALL GREEN - 신규 unit tests ✅ 2 PASS - 광범위 sweep 7 fixture / 170 페이지 / **회귀 0** ✅ - 시각 판정 면제 합리 (PNG 메타데이터 영역 영역 픽셀 데이터 무영향, feedback_visual_judgment_authority 정합) closes #614
- mydocs/pr/archives/pr_734_review.md: 검토 문서 archives 이동 - mydocs/pr/archives/pr_734_report.md: 처리 보고서 작성 · export-png --dpi 옵션 (Issue #614 closes) · PNG pHYs chunk 영역 인쇄 워크플로우 메타데이터 · 작업지시자 실 sample 검증 통과 (samples/통합재정통계(2010.11월).hwp 영역 4 패턴) · 시각 판정 면제 합리 (PNG 메타데이터 영역 영역 픽셀 데이터 무영향) - mydocs/orders/20260510.md: PR #734 항목 추가 (5/10 사이클 영역 영역 8건 처리) - mydocs/manual/export_png_command.md: --dpi 옵션 매뉴얼 현행화 · 옵션 표 영역 --dpi 추가 · 옵션 우선순위 갱신 (--dpi auto-scale) · DPI 메타데이터 영역 영역 별도 절 추가 (PNG spec §11.3.5.3 정합) · 사용 예시 + 출력 dimension 표 갱신 (--dpi 300 영역 영역) · 출력 형식 영역 메타데이터 명시 · 비목표 영역 갱신 (PR #720/#734 영역 영역 진전 반영)
|
@oksure 님, 검토 + 머지 완료했습니다. 처리 결과옵션 A (2 commits cherry-pick + no-ff merge `d76e86fc`) 로 처리. 자기 검증
작업지시자 실 sample 검증 ✅`samples/통합재정통계(2010.11월).hwp` 영역 영역 4 패턴 검증 — 모두 정합 영역:
검증 영역 영역:
시각 판정 면제`feedback_visual_judgment_authority` 정합 — PNG 메타데이터 영역 영역 (픽셀 데이터 무영향), SVG 시각 출력 무변경, 결정적 검증 통과 영역 영역 시각 판정 면제 합리. 매뉴얼 현행화`mydocs/manual/export_png_command.md` 영역 `--dpi` 옵션 추가 영역 영역 매뉴얼 현행화 완료 (옵션 표 + 옵션 우선순위 + DPI 메타데이터 별도 절 + 사용 예시 + 출력 dimension 표 + 비목표 갱신). 처리 보고서: `mydocs/pr/archives/pr_734_report.md`. @oksure 님 20+ 사이클 컨트리뷰션 영역 — 5/10 사이클 영역 영역 PR #720/#723/#725/#728/#729/#730/#732/#734 영역 8건 처리 완료 영역. |
…wen-VL / LLaVA) PR #735 (@oksure) 옵션 A 처리 — 2 commits cherry-pick + 수동 충돌 해결 + no-ff merge. 본질 정정 (2 files, +71/-8): - src/document_core/queries/rendering.rs (+61/-3): VlmTarget enum 1 → 6 variants 확장 (Claude / Gpt4vLow / Gpt4vHigh / Gemini / QwenVl / Llava) + constraints() 메서드 각 provider 한도 (edge / pixels) + from_str() 하이픈/밑줄 정규화 + 축약 별칭 (gpt4v / qwen) + all_names() 헬퍼 + 신규 unit tests 2건 (vlm_target_from_str_all_variants 12 케이스 / vlm_target_constraints_are_sane 6 variants sanity check) - src/main.rs (+10/-5): CLI 도움말 영역 6종 프리셋 한 줄 설명 + 에러 메시지 영역 VlmTarget::all_names() 동기화 추가 프리셋: - gpt4v-low: 512 px / 262K (GPT-4V low detail) - gpt4v-high: 2000 px / 1.54 MP (GPT-4V high, 별칭 gpt4v) - gemini: 3072 px / 9.44 MP (Google Gemini) - qwen-vl: 2240 px / 5.02 MP (Qwen-VL 28×28 patch, 별칭 qwen) - llava: 672 px / 452K (LLaVA / OSS CLIP backbone) Copilot 리뷰 반영 (commit 2883733): from_str 정규화 후 dead arm 제거 + 별칭 도움말 동기화 (하이픈/밑줄 모두 허용 명시). 본 환경 cherry-pick 영역 영역 PR #734 (Task #614 --dpi) 영역 영역 동일 파일 영역 영역 누적 변경 영역 영역 충돌 발생 영역 영역 → **수동 통합** (PR #734 의 --dpi 보존 + PR #735 의 VLM 6종 보존). 자기 검증: - cherry-pick 2 commits 영역 영역 수동 충돌 해결 (main.rs 도움말 + rendering.rs 테스트 모듈) - cargo build/test --release ✅ ALL GREEN (native-skia feature 영역 영역 도) - VLM unit tests ✅ 2 PASS - 광범위 sweep 7 fixture / 170 페이지 / **회귀 0** ✅ - --dpi + --vlm-target 통합 동작 검증 ✅ (samples/통합재정통계(2010.11월).hwp 영역 영역 --vlm-target gemini 단독 + --vlm-target gpt4v --dpi 200 동시 — pHYs ppm 7874 = 200 DPI 정합) opt-in 영역 영역: - --vlm-target 미지정 시 기존 동작 100% 보존 - 시각 판정 면제 합리 (CLI 옵션 + enum 확장 영역 영역 픽셀 데이터 무영향, feedback_visual_judgment_authority 정합) closes #613
…M 프리셋 표 갱신 - mydocs/pr/archives/pr_735_review.md: 검토 문서 archives 이동 - mydocs/pr/archives/pr_735_report.md: 처리 보고서 작성 · VLM 프리셋 1 → 6 variants 확장 (Issue #613 closes) · PR #734 + PR #735 동일 파일 누적 변경 영역 영역 수동 통합 · PR #734 + PR #735 통합 검증 ✅ (--vlm-target + --dpi 독립 동작 입증) · 시각 판정 면제 합리 (CLI + enum 확장 영역 영역 픽셀 데이터 무영향) - mydocs/orders/20260510.md: PR #735 항목 추가 (5/10 사이클 영역 영역 9건 처리) - mydocs/manual/export_png_command.md: VLM 프리셋 표 갱신 (1 → 6 variants) + 비목표 영역 갱신 (#613 완료)
요약
export-png명령에--dpi <값>옵션을 추가합니다.pHYschunk 에 DPI 메타데이터를 삽입하여 인쇄 워크플로우에서 크기 힌트를 제공합니다--scale미지정 시scale = dpi / 96.0자동 계산 (예:--dpi 300→ scale 3.125)변경 사항
PngExportOptions에dpi: Option<f64>필드 추가--dpi <값>옵션 파싱 + 도움말 갱신pHYschunk 후처리 삽입 (IHDR 직후, PNG spec §11.3.5.3)사용 예시
테스트
Closes #614
감사합니다.