这里已经有很多关于使用Ghostscript裁剪文档的问题和答案。 但是,答案与我的确切需求不符,并且仍然让我感到困惑。 我预计会有一个选项,例如“-AutoCropToBBox”或类似的东西。
为了澄清,作为一个边界框,我理解最小的矩形框,它完全包含所有(非白色(?))打印对象。
此外,我希望/必须使用打印机端口重定向(RedMon)通过从任何应用程序打印到Postscript打印机来生成裁剪的PDF。 因此,在Win7 / 64bit下,我设置了重定向的端口属性: Redirected port properties Win7/64bit
输出重定向到
C:\Windows\system32\cmd.exe
该计划的论据是:
/c gswin64c.exe -sDEVICE=pdfwrite -o -sOutputFile="%1".pdf -
“%1”包含filename的用户输入。有了这个,我得到一整页PDF。精细!
但是如何添加裁剪选项?
其他问题: 如果我有一个多页文档,这样的(自动)裁剪是否适用于每个页面?或者是否可以选择保持相同,例如像第一页或所有页面的最大边界框?
另一个相关问题: 提示文件名的窗口总是弹出我正在打印的应用程序后面。总是把它带到前线的任何想法?
另一个问题: 有Perl脚本“ps2eps”和程序bbox.exe(见http://ctan.org/pkg/ps2eps)。据说Ghostscript(或ps2epsi)是在计算错误的边界框。这(仍然)是真的吗?
感谢您的帮助。
答案 0 :(得分:2)
你的第一个问题是,PostScript程序通常被编写为期望被渲染到特定的媒体大小,并且通常不会紧密地限制它。白色空间对于可读性非常重要。
通常,您生成的PostScript程序将请求特定的媒体大小,解释器将尽力匹配。如果它无法匹配,那么它将使用策略尝试尽可能接近,并缩放整个内容以适应该媒体。
如果打印机在完成之前不知道所需的尺寸,则不能指望打印机执行任何这些操作,并且在渲染完所有标记内容之前,您无法确定边界框。确实有些文件通常是EPS文件有一个%% BoundingBox注释但是......这是一个注释,它在PostScript中没有任何效果,它有利于那些不想解释PostScript的应用程序。
这就是为什么你想要的简单开关不存在,它会破坏解释器的正常功能,以便渲染。
因此,您需要做的第一件事是确定内容的边界框。正如Stefan所说,你可以通过使用bbox设备来做到这一点。就此而言,据我所知,bbox设备可以产生准确的输出。如果没有,那么我们将非常感谢错误报告证明它,以便我们可以解决它。如果人们不报告错误我们应该如何了解它们?令人失望的是看到有人传播FUD而不是帮忙搞错误报告.......
ps2epsi不是Ghostscript,它是一个糟糕而又开朗的脚本,我不会用它。但是.....如果原始的PostScript在堆栈上留下了东西,那么它最终将成为损坏的(或无效的)EPS文件,并且在尝试使用它之前应修复原始的PostScript,因为它会破坏任何尝试的PostScript程序使用它(例如,如果您将EPS包含在docuemnt中然后打印它)。
因此,如果您正在使用Ghostscript,并且想要使用PostScript程序并从中获取EPS,请使用eps2write设备。坦白地说它不会有任何关注的预览。
现在如果我没记错bbox设备(和eps2write)记录所有标记操作,你不能简单地记录所有非白色标记操作;如果白色覆盖页面上的现有标记怎么办?如果媒体不白色怎么办?请注意,如果使用Ghostscript渲染到PNG,则输出的未触摸部分是透明的,而白色标记则不是。
因此,无论颜色如何,bbox都是所有标记操作的范围。唯一的其他方法是渲染内容并计算非白色像素。但这仅适用于特定分辨率,更改分辨率,精确的边界框也可能会发生变化。
一旦你有了边框,你可以告诉Ghostscript使用那么大的媒体。请注意,您几乎肯定会也必须翻译原点,因为内容不太可能在左下角紧密开始。您将需要-dDEVICEWIDTHPOINTS和-dDEVICEHEIGHTPOINTS来设置介质大小,您需要使用-c和-f发送PostScript以适当地更改原点。在简单的情况下,'-x -y translate'就足够了,但如果程序执行initgraphics,你将不得不设置一个BeginPage程序来改变初始CTM。
如果使用-dDEVICEWIDTHPOINTS等设置媒体大小,则所有页面的大小都相同。如果您不想这样,那么您需要编写一个BeginPage过程来单独调整每个页面的大小(您还需要挂钩setpagedevice并从字典中删除/ PageSize条目。
我不知道为什么Windows将对话框放在活动窗口后面,它似乎已经开始使用Windows 7(或可能是Vista)。我没有看到任何改变方法,因为我不确定是什么产生了对话.......
我个人建议您尝试通过Ghostscript的eps2write设备运行原始文件的两步方法,然后使用pdfwrite设备和-dEPSCrop开关获取EPS并创建PDF文件。双重转换很糟糕,但其他解决方案更糟糕。请注意,EPS文件不能是多页的,因此您必须从n页PostScript程序创建'n'EPS文件,然后提供一个命令行,列出每个EPS文件作为输入到pdfwrite device。
获取示例文件并在尝试编写脚本之前从命令行尝试此操作。
答案 1 :(得分:0)
正如我从@KenS解释中所理解的那样:
因此,我现在最终使用以下过程“打印”具有正确最小可能边界框的PDF:
将重定向的打印机端口重定向到cmd.exe
C:\Windows\system32\cmd.exe
该计划的论点:
/c gswin64c.exe -q -o "%1".ps -sDEVICE=ps2write - && gswin64c.exe -q -dBATCH -dNOPAUSE -sDEVICE=bbox -dLastPage=1 "%1".ps 2>&1 >nul | perl.exe C:\myFiles\CropPS2PDF.pl "%1"
不幸的是,它需要一个小的Perl脚本(让我们称之为:CropPS2PDF.pl):
#!usr/bin/perl -w
use strict;
my $FileName = $ARGV[0];
$/ = undef;
my $Crop = <STDIN>;
$Crop =~ /%%BoundingBox: (\d+) (\d+) (\d+) (\d+)/s; # get the bbox coordinates
my ($llx, $lly, $urx, $ury) = ($1, $2, $3, $4);
print "\n$FileName: $llx, $lly, $urx, $ury \n"; # print just to check
my $Command = qq{gswin64c.exe -q -o $FileName.pdf -sDEVICE=pdfwrite -c "[/CropBox [$llx $lly $urx $ury]" -c " /PAGE pdfmark" -f $FileName.ps};
print $Command; # print just to check
system($Command); # execute command
似乎工作...... :-) 欢迎改进。
我的问题仍然存在: