使用 ghostscript 从 stdin(string) 到 stdout 将 PDF 转换为 Jpg
Convert PDF to Jpg with ghostscript from stdin(string) to stdout
我正在尝试在 php 中使用 ghostscript 将多页 pdf 转换为 jpg。现在的命令看起来像这样:
gs -q -dBATCH -sDEVICE=jpeg -dNOPAUSE -dSAFER -dJPEGQ=100 -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -r72 -sOutputFile=- some.pdf
我想要的是找到一种方法将 pdf 作为字符串输入,看起来像这样:'%PDF-1.4 %���� 1 0 obj <> endobj 2 0 obj <> endobj 等。 '并将所有页面输出到标准输出。向命令提供实际的 pdf 文件效果很好,但它 returns 一页。如果选择文件写入,则有一个选项 p%03d.jpg 来获取所有页面,但我需要将其转储到 temp/memory。据我了解,您需要使用管道才能使其正常工作。我用 proc_open() 做了一些但没有成功,因为我不知道如何将字符串传递给管道。
$args = [
'-dBATCH',
'-sDEVICE=jpeg',
'-dNOPAUSE',
'-dSAFER',
'-dJPEGQ=100',
'-dGraphicsAlphaBits=4',
'-dTextAlphaBits=4',
'-r72',
'-sOutputFile=-',
$path . '/some.pdf'// this shouold be passed as string stdin
];
$descr = [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe','w']
];
$pipes = array();
$args = implode(' ', $args);
$commd = "gs -q $args";
$process = proc_open($commd, $descr, $pipes);
$response = '';
if (is_resource($process)) {
fputs($pipes[0], $pdf);
fclose($pipes[0]);
while ($f = fgets($pipes[1])) {
$response .= $f;
}
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
}
echo '<img src="data:image/png;base64, ' . base64_encode($response) . '" />';
更新:
找到输入的解决方案。它是一个破折号,而不是表示输入文件的最后一个参数。多页输出仍然是一个问题。
我已经在本地测试了这段代码并且正在为我工作:
我正在使用 passthru to direct output answer, and play around output buffering 捕捉一个
<?php
$command = "/path/to/gs -dBATCH -sDEVICE=jpeg -dNOPAUSE -dSAFER -dJPEGQ=100 -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -r72 -sOutputFile=- ./someFile.pdf";
// Capture output on buffer.
ob_start();
// Will automatically output answer of your command
passthru($command);
// you get buffered output.
$response = ob_get_contents();
// Flush buffer.
ob_end_clean();
echo '<img src="data:image/png;base64, ' . base64_encode($response) . '" />';
您无法使用 Ghostscript 在内存中呈现 PDF 文件。
Ghostscript 仅处理磁盘中的 PDF 文件。如果您通过管道从 stdin 输入,所有发生的事情就是 Ghostscript 创建一个临时文件,将 PDF 存储在其中,然后呈现该临时文件。这是因为 PDF 文件固有地需要在文件内随机查找的能力。
所以实际上,通过标准输入发送文件,您只是将临时文件的创建转移到 Ghostscript 内部完成,而不是您自己完成。如果您认为这样做可以以某种方式提高性能,那您就错了。
如果您指定 -
(stdout) 作为输出文件,那么 all 输出将发送到 stdout。如果不止一页,那么两页都被发送到输出(它还能做什么?)。由您决定每一页的结束位置并将其拆分。
如果您省略 -q
并查看发送到 stdout 的内容(例如,通过将其重定向到文件),您将看到在开始时发送了通常的 Ghostscript 样板文件。如果你进一步省略 -dNOPAUSE
(注意你需要为每个页面按 'return' 并且不会提示你,所以只需敲击一下键)然后查看输出你会看到每页由
分隔
>>showpage, press <return> to continue<<
因此您可以看到每个页面都已发送,由您决定每个 JPEG 的结尾位置。
考虑到您要将多页输出发送到标准输出,我不确定您还希望发生什么。
我正在尝试在 php 中使用 ghostscript 将多页 pdf 转换为 jpg。现在的命令看起来像这样:
gs -q -dBATCH -sDEVICE=jpeg -dNOPAUSE -dSAFER -dJPEGQ=100 -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -r72 -sOutputFile=- some.pdf
我想要的是找到一种方法将 pdf 作为字符串输入,看起来像这样:'%PDF-1.4 %���� 1 0 obj <> endobj 2 0 obj <> endobj 等。 '并将所有页面输出到标准输出。向命令提供实际的 pdf 文件效果很好,但它 returns 一页。如果选择文件写入,则有一个选项 p%03d.jpg 来获取所有页面,但我需要将其转储到 temp/memory。据我了解,您需要使用管道才能使其正常工作。我用 proc_open() 做了一些但没有成功,因为我不知道如何将字符串传递给管道。
$args = [
'-dBATCH',
'-sDEVICE=jpeg',
'-dNOPAUSE',
'-dSAFER',
'-dJPEGQ=100',
'-dGraphicsAlphaBits=4',
'-dTextAlphaBits=4',
'-r72',
'-sOutputFile=-',
$path . '/some.pdf'// this shouold be passed as string stdin
];
$descr = [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe','w']
];
$pipes = array();
$args = implode(' ', $args);
$commd = "gs -q $args";
$process = proc_open($commd, $descr, $pipes);
$response = '';
if (is_resource($process)) {
fputs($pipes[0], $pdf);
fclose($pipes[0]);
while ($f = fgets($pipes[1])) {
$response .= $f;
}
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
}
echo '<img src="data:image/png;base64, ' . base64_encode($response) . '" />';
更新: 找到输入的解决方案。它是一个破折号,而不是表示输入文件的最后一个参数。多页输出仍然是一个问题。
我已经在本地测试了这段代码并且正在为我工作:
我正在使用 passthru to direct output answer, and play around output buffering 捕捉一个
<?php
$command = "/path/to/gs -dBATCH -sDEVICE=jpeg -dNOPAUSE -dSAFER -dJPEGQ=100 -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -r72 -sOutputFile=- ./someFile.pdf";
// Capture output on buffer.
ob_start();
// Will automatically output answer of your command
passthru($command);
// you get buffered output.
$response = ob_get_contents();
// Flush buffer.
ob_end_clean();
echo '<img src="data:image/png;base64, ' . base64_encode($response) . '" />';
您无法使用 Ghostscript 在内存中呈现 PDF 文件。
Ghostscript 仅处理磁盘中的 PDF 文件。如果您通过管道从 stdin 输入,所有发生的事情就是 Ghostscript 创建一个临时文件,将 PDF 存储在其中,然后呈现该临时文件。这是因为 PDF 文件固有地需要在文件内随机查找的能力。
所以实际上,通过标准输入发送文件,您只是将临时文件的创建转移到 Ghostscript 内部完成,而不是您自己完成。如果您认为这样做可以以某种方式提高性能,那您就错了。
如果您指定 -
(stdout) 作为输出文件,那么 all 输出将发送到 stdout。如果不止一页,那么两页都被发送到输出(它还能做什么?)。由您决定每一页的结束位置并将其拆分。
如果您省略 -q
并查看发送到 stdout 的内容(例如,通过将其重定向到文件),您将看到在开始时发送了通常的 Ghostscript 样板文件。如果你进一步省略 -dNOPAUSE
(注意你需要为每个页面按 'return' 并且不会提示你,所以只需敲击一下键)然后查看输出你会看到每页由
>>showpage, press <return> to continue<<
因此您可以看到每个页面都已发送,由您决定每个 JPEG 的结尾位置。
考虑到您要将多页输出发送到标准输出,我不确定您还希望发生什么。