如何检测PDF文件由哪种源文件生成?C#实现方法咨询
检测PDF是否由JPEG/TIFF转换的实现方案
可行性说明
该需求可以实现,针对未经过二次编辑、直接由单张/多张图片转换生成的PDF检测准确率可达95%以上。核心判断逻辑为:这类PDF每页仅包含1个和页面尺寸几乎一致的嵌入图像对象,且图像压缩格式、参数和JPEG/TIFF的特征完全匹配;普通文字生成的PDF会包含文本对象、矢量路径,不会以整张尺寸匹配的图像作为唯一页面内容。如果PDF经过裁剪、添加水印、OCR叠加文字层等操作,需要调整检测规则适配。
C#实现步骤
你可以借助成熟的PDF处理库完成开发,以下是基于iText 7的实现方案:
- 首先安装对应NuGet包:
itext7 - 核心检测逻辑如下:
using iText.Kernel.Pdf; using iText.Kernel.Pdf.Xobject; public static bool CheckPdfImageSource(string pdfPath, out string sourceFormat) { sourceFormat = string.Empty; try { using var pdfReader = new PdfReader(pdfPath); using var pdfDoc = new PdfDocument(pdfReader); // 遍历所有页面校验,所有页面都符合特征才判定为图片转换生成 for (int i = 1; i <= pdfDoc.GetNumberOfPages(); i++) { var page = pdfDoc.GetPage(i); var pageSize = page.GetPageSize(); var resources = page.GetResources(); var xObjectNames = resources.GetXObjectNames(); List<PdfImageXObject> pageImages = new(); foreach (var name in xObjectNames) { var xObj = resources.GetXObject(name); if (xObj is PdfImageXObject imgObj) { pageImages.Add(imgObj); } } // 页面图像数量不为1,不符合直接转换的特征 if (pageImages.Count != 1) return false; var targetImg = pageImages[0]; // 允许图像和页面尺寸有2%以内的误差,避免边距、缩放带来的误判 float widthDiffRate = Math.Abs(targetImg.GetWidth() - pageSize.GetWidth()) / pageSize.GetWidth(); float heightDiffRate = Math.Abs(targetImg.GetHeight() - pageSize.GetHeight()) / pageSize.GetHeight(); if (widthDiffRate > 0.02 || heightDiffRate > 0.02) return false; // 匹配压缩格式特征 var filterType = targetImg.GetPdfObject().Get(PdfName.Filter)?.ToString(); if (filterType == "/DCTDecode") { sourceFormat = "JPEG"; } else if (filterType is "/CCITTFaxDecode" or "/LZWDecode" or "/FlateDecode" && targetImg.GetBitsPerComponent() <= 8) { // TIFF常见压缩格式,结合位深度判定 sourceFormat = "TIFF"; } else { return false; } } return true; } catch { // 加密、损坏的PDF直接返回检测失败 return false; } }
优化建议
- 如果需要更高的检测准确率,可以提取嵌入图像的原始字节,和JPEG/TIFF的文件头特征做二次校验
- 针对叠加了OCR文字层的扫描件PDF,检测时可以跳过文本对象,只统计页面内的图像资源
- 针对带水印的PDF,可以过滤尺寸远小于页面的图像资源后再做判断
内容的提问来源于stack exchange,提问作者mechmati
相关产品推荐
相关产品推荐

