首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
FairScan如何快速生成PDF:PDFBox-Android与CCITT G4压缩优化实战
📅 2026/10/23 4:08:52
✍️ 爱科研究院
👁 阅读 3,247
【免费下载链接】FairScanAn Android app to scan your documents — simple and respectful项目地址https://gitcode.com/gh_mirrors/fa/FairScan点击查看免费下载FairScan 是一款开源的 Android 文档扫描应用。本文带你拆解它如何基于 PDFBox-Android 在手机上快速生成 PDF并用 CCITT G4 压缩把黑白页面体积降到极小、同时让文字依然清晰可搜——即使不写一行代码你也能理解这份小体积 高清晰背后的完整设计思路。在 FairScan 里从拍照到得到一份可分享的 PDF 只需几秒钟。但快背后藏着不少工程取舍用哪个 PDF 库黑白页和彩色页该怎么编码页面尺寸如何对齐真实纸张本文沿真实源码把这些问题讲清楚。一、扫描流程全景先看图再谈压缩FairScan 的处理管线是拍摄 → 检测文档边缘 → 透视矫正 → 增强 → 导出 PDF全部在本地完成不经过任何云端。下面这张图就是一张等待处理的文档照片FairScan 会自动把页面从桌面背景中抠出来真正与生成 PDF相关的代码集中在一条调用链上界面层ExportViewModel.kt 负责点击导出后准备数据文件层FileManager.kt 通过PdfWriter接口写出 PDF 文件实现层AndroidPdfWriter.kt 把每页图片画进 PDF 文档这种接口 实现的分层设计很典型PdfWriter是一个只含一个方法的函数式接口FileManager.kt 中的fun interface将来换成别的 PDF 库时上层代码完全不用动。二、为什么选 PDFBox-Android桌面 Java 世界里写 PDF 几乎人人用 PDFBox但原生的 PDFBox 依赖 Java AWT无法直接跑在 Android 上。FairScan 的答案是使用 PDFBox 的 Android 移植版pdfbox-android版本集中在 libs.versions.toml 中统一管理依赖坐标com.tom-roush:pdfbox-android:2.0.27.0包名从org.apache.pdfbox换成了com.tom_roush.pdfboxAPI 与桌面版基本一致于是 AndroidPdfWriter.kt 里的写 PDF 流程就是教科书式的三步创建PDDocument写入创建时间和作者信息为每一页创建PDPage用PDPageContentStream.drawImage把图片画满整页全部画完后document.save(outputStream)一次落盘这里有一个新手容易忽略的细节PDF 页面的单位是 point点1 英寸 72 point。FairScan 利用这个约定把像素换算成物理尺寸AndroidPdfWriter.kt知道纸张真实毫米尺寸时比如 A4 合同直接按毫米换算不知道时按A4 高度等比缩放兜底并且用constrainToMaxFormat函数把页面约束在 Letter 宽到 A4 高的合理区间内避免生成的 PDF 页面大得离谱或小到无法阅读。三、CCITT G4 压缩黑白页为什么能小几个数量级彩色照片用 JPEG 天经地义但黑白文档页有个特殊优势每个像素只有黑/白两种状态1 个 bit 就够。FairScan 对黑白页走了完全不同的编码路线这也是本文的核心。第一步是二值化。在 PostProcessing.kt 中binarizeDocument使用 Sauvola 自适应阈值把灰度图变成纯黑白图再配合去噪点、填孔等操作消除阴影和背景噪纹。第二步是位打包。BitonalPacking.kt 里的packBitsMsbFirst函数把黑白图像压缩成每像素 1 bit的紧凑数组每 8 个像素挤进 1 个字节从高位开始MSB first每行按整字节补齐位被置 1 表示黑色——这个约定恰好符合 CCITT 编码器的默认行为得到的数据结构非常简洁定义在 Image.kt// One bit per pixel, MSB first, rows padded to whole bytes, set bit means black. class Bitonal(val width: Int, val height: Int, val bits: ByteArray)第三步是调用 CCITT G4 编码器。CCITT国际电报电话咨询委员会G4 是传真标准的压缩算法对大片白色 稀疏黑色文字的文档页有极佳的压缩率。FairScan 直接用 PDFBox 内置的CCITTFAX_DECODE过滤器来完成编码AndroidPdfWriter.ktFilterFactory.INSTANCE.getFilter(COSName.CCITTFAX_DECODE) .encode(ByteArrayInputStream(bitonal.bits), encoded, decodeParms, 0)这里藏着两个关键参数参数值含义COLUMNS/ROWS图像宽高解码端还原尺寸所必需K-1K 0即 Group 4二维模式压缩率最高源码注释还解释了一个避坑点PDFBox 自带的CCITTFactory强制要求ALPHA_8位图FairScan 无法复用于是照着官方调用序列手写了一遍同时因为编码器把置 1 的位读作黑色所以故意不设置/BlackIs1。对比一下效果就明白了一张 2100×2800 的纯黑白 JPEG 大约要几 MB而同一页经 CCITT G4 编码后往往只有几十 KB——体积缩小几十倍画质却无损因为 1 bit 本身就承载了页面全部信息。而彩色或灰度页则回退到 JPEGJPEGFactory.createFromByteArray直接嵌入AndroidPdfWriter.kt。两条路线的选择只取决于一行判断——页面颜色模式是否为BLACK_AND_WHITE。四、三档导出质量清晰度与体积的平衡快而小不等于一味压缩。FairScan 提供了 LOW / BALANCED / HIGH 三档质量ExportQuality.kt差异体现在两个维度档位JPEG 质量像素上限适用场景LOW60100 万快速分享、节省存储BALANCED75200 万日常默认HIGH80400 万需要放大阅读细节注意一个精巧的设计黑白档位的像素上限是彩色档的4 倍maxPixels * 4。原因正呼应上一节——黑白页每像素只有 1 bit同样分辨率下编码后依然极小所以可以放心保留更多细节。质量对导出结果的影响在 ExportPreparation.kt 中落地LOW 档会把图片缩到像素上限以内再编码HIGH 档则回到原始照片重新走一遍完整处理管线。五、隐藏彩蛋OCR 文字层让 PDF 可搜索上面这张黑白书页扫描图如果直接导出成图片 PDF文字是无法被搜索和复制的。FairScan 的做法是在 PDF 里叠加一层不可见的隐藏文字层实现看图是图、复制是字实现同样在 AndroidPdfWriter.kt调用 Tesseract OCR 拿到每个文字行的文本和位置嵌入一个无字形字体TesseractGlyphLessFont.ttf——这个字体只有度量信息、没有字形轮廓专门用来给 PDF 阅读器做文本选择生成一份 ToUnicode CMap 映射让任意 Unicode 字符都能被正确识别思路直接借鉴自 Tesseract 官方的pdfrenderer.cpp。另外有个性能细节黑白页在 PDF 里是 4 倍像素密度OCR 时先用halfSize缩回一半避免文字识别白白多花 4 倍时间。六、核心模块速查模块职责文件PDF 写入与 CCITT G4 编码组装 PDF、嵌入图像、OCR 文字层AndroidPdfWriter.kt位打包1 bit/像素MSB first 打包/解包BitonalPacking.kt二值化与去噪Sauvola 阈值、填孔、去噪点PostProcessing.kt导出质量定义三档质量与像素上限ExportQuality.kt导出前准备按质量分档处理页面ExportPreparation.kt依赖版本pdfbox-android 2.0.27.0libs.versions.toml七、小结可复用的三个经验如果你也在做移动端文档扫描类应用FairScan 的这套方案有几点可以直接借鉴分模式编码黑白页走 CCITT G41 bit/像素 传真编码彩色页走 JPEG一行判断即可分流收益是数量级的位图约定要写清楚Bitonal的注释置 1 为黑、MSB first、按字节补齐是编码与解码双方不出错的保障页面单位用物理量以毫米 → 72 点/英寸换算页面尺寸并约束在 Letter/A4 区间生成的 PDF 在任何阅读器里都大小合适FairScan 证明了不依赖云端、只用开源组件也能在手机上做出秒出 PDF、体积小、文字可搜索的文档扫描体验。想深入阅读源码时从 AndroidPdfWriter.kt 这个入口一路跟下去你会发现整个导出过程比想象中更清晰。赞分享【免费下载链接】FairScanAn Android app to scan your documents — simple and respectful项目地址https://gitcode.com/gh_mirrors/fa/FairScan点击查看免费下载相关推荐终极指南如何快速优化Android字体压缩与Calligraphy应用终极指南如何快速优化Android字体压缩与Calligraphy应用 想让你的Android应用拥有独特的字体风格同时保持APK体积精简吗Calligr移动开发UI组件如何快速掌握HTMLMinifier新手压缩优化的完整实战指南 如何快速掌握HTMLMinifier新手压缩优化的完整实战指南 HTMLMinifier是一款基于JavaScript的高性能HTML压缩器专门用于优前端开发工具构建工具Android视频压缩终极指南如何快速优化视频文件大小Android视频压缩终极指南如何快速优化视频文件大小 VideoCompressor是一个基于Android硬件编解码APIMediaCodec的高性能音视频上一篇Sub-Zero与Bazarr对比为什么这仍是Plex用户的最佳字幕解决方案下一篇LXMusic开源项目音源配置技术解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/10/23 4:03:52
MATLAB常见问题30秒速查与高效排障指南
2026/10/23 4:03:52
libva中的DRM模块
2026/10/23 4:03:52
Java:54-Linux概述
2026/10/23 4:53:58
000网络物理隔离
2026/10/23 4:53:58
企业微信自动回复的词条怎么定期清理?三类该淘汰的
2026/10/23 4:53:58
Python后端工程化与测试10:测试越写越脆,先查替身和fixture放在哪里
2026/10/23 4:53:58
数据结构——B树(B-树)与B+树
2026/10/23 4:53:58
Git常用命令【扩展】
2026/10/23 4:48:57
基于 Java Spring Boot 的车队管理系统设计与实现
2026/10/23 0:02:44
Verilog实现FPGA密码锁:矩阵键盘与状态机设计实战
2026/10/23 0:02:44
数据服务监控运维实战:从指标体系到告警治理与故障排查
2026/10/23 0:02:44
FreeRTOS任务通知实战详解:内核原理、API与避坑指南
2026/10/23 0:52:23
OpenResearch实战:Claude Code、Codex、OpenCode、Cursor 工作流搭建与故障排查
2026/10/22 17:15:21
知识管理核弹:用Obsidian构建第二大脑的工程化方案(TaoToken 统一 Key 接入版)
2026/10/23 0:52:11
金融AI落地指南:从调研报告到技术选型与工程实践
2026/10/22 5:06:15
我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
2026/10/22 2:07:18
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026/10/21 19:01:08
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)