如何统计含图片的PDF页数及图片总数?已试Imagick及正则方法未果
解决PDF图片统计问题的可行方案
嘿,我明白你用Imagick的identifyImage()和正则匹配都卡壳的烦恼——确实,PDF的图片嵌入方式五花八门,这俩方法有时候不太顶用。给你几个更靠谱的思路:
方法一:用pdfimages命令行工具(最推荐)
这是专门处理PDF图片的工具,属于poppler-utils包(大多数Linux发行版可以直接装,Windows/macOS也有对应安装包),能精准统计图片总数和对应页码。
步骤:
- 先安装
poppler-utils(比如Ubuntu用sudo apt install poppler-utils) - 在PHP里调用命令并解析输出:
$pdfPath = 'your_file.pdf'; // 执行pdfimages命令,获取详细列表 $output = shell_exec("pdfimages -list $pdfPath"); // 解析输出:跳过表头,剩下的每一行对应一张图片 $lines = explode("\n", trim($output)); array_shift($lines); // 移除表头行 $totalImages = count($lines); $pagesWithImages = []; foreach ($lines as $line) { $parts = preg_split('/\s+/', $line); $pageNum = $parts[1]; if (!in_array($pageNum, $pagesWithImages)) { $pagesWithImages[] = $pageNum; } } echo "PDF总图片数:$totalImages\n"; echo "包含图片的页码:" . implode(', ', $pagesWithImages) . "\n";
这个方法几乎能覆盖所有常规PDF的图片统计,包括单页单图的情况。
方法二:改进Imagick的使用方式
如果不想依赖外部工具,可以试试通过导出页面为SVG来检测图片:
$pdf = new Imagick(); $pdf->readImage('your_file.pdf'); $totalImages = 0; $pagesWithImages = []; // 遍历每一页 foreach ($pdf as $index => $page) { $pageNum = $index + 1; // 页码从1开始计数 // 将页面导出为SVG格式,SVG会把图片用<image>标签标记 $svgContent = $page->getImageBlob('SVG'); // 匹配所有<image>标签 preg_match_all('/<image[^>]+>/i', $svgContent, $matches); $imageCount = count($matches[0]); if ($imageCount > 0) { $pagesWithImages[] = $pageNum; $totalImages += $imageCount; } } $pdf->clear(); $pdf->destroy(); echo "总图片数:$totalImages\n"; echo "含图片的页码:" . implode(', ', $pagesWithImages) . "\n";
注意:这个方法对某些特殊嵌入的图片(比如作为背景的位图、矢量图转成的图片)可能漏检,但胜在纯PHP实现。
方法三:解析identify -verbose的输出
用Imagick的命令行工具输出详细信息,再提取图片相关内容:
$pdfPath = 'your_file.pdf'; $output = shell_exec("identify -verbose $pdfPath"); // 匹配所有图片条目,提取页码和数量 preg_match_all('/Image:\s+\d+\s+Page:\s+(\d+)/', $output, $matches); $totalImages = count($matches[0]); $pagesWithImages = array_unique($matches[1]); echo "总图片数:$totalImages\n"; echo "含图片的页码:" . implode(', ', $pagesWithImages) . "\n";
这个方法的准确性依赖于Imagick对PDF的解析程度,有时候会比直接用identifyImage()靠谱些。
内容的提问来源于stack exchange,提问作者ohayou




