Ghostscript -- 将 PS 转换为 PNG、旋转和缩放

Posted

技术标签:

【中文标题】Ghostscript -- 将 PS 转换为 PNG、旋转和缩放【英文标题】:Ghostscript -- convert PS to PNG, rotate, and scale 【发布时间】:2019-02-11 18:36:54 【问题描述】:

我有一个应用程序可以创建非常漂亮的以 PostScript 呈现的数据图,具有字母大小和横向模式。输入文件的示例位于http://febo.com/uploads/blip.ps。 [注意:此图像在查看器中正确呈现,但 PNG 转换与图像横向显示。 ] 我需要将这些 PostScript 文件转换为按比例缩小并旋转 90 度以进行 Web 演示的 PNG 图像。

我想用ghostscript而不是其他外部工具来做这个,因为转换程序将在Windows和Linux系统上使用,gs似乎是一个共同点。 (我正在创建一个带有“PS2png”函数的 perl 脚本,该函数将调用 gs,但我认为这与问题无关。)

我在网上搜索并花了几天时间尝试修改我找到的示例,但我没有尝试过 (a) 旋转、(b) 调整大小、(c) 保持纵横比的组合(d) 避免剪裁。

我确实找到了一个将“缩放”命令注入 postscript 流的示例,这似乎可以很好地将图像缩放到所需的大小,同时保持纵横比。但我找不到一种方法来旋转调整大小的图像,以便例如 601 x 792 点(2504 x 3300 像素)的后记输入变成 800 x 608 像素的 png 输出。

我正在寻找可以传递给 gs 命令行来完成此操作的 ghostscript/postscript fu。

我尝试了 gs 命令行与 -dFIXEDMEDIA、-dFitPage、-dAutoRotatePages=/None 或 /All、-c " setpagedevice" 的各种组合、更改 -dDISPLAYWIDTHPOINTS 和 -dDISPLAYHEIGHTPOINTS、-g[width] x[height],带有旋转坐标的 -dUseCropBox 以及其他我忘记的东西。这些都不起作用,尽管如果其中一些神奇的组合会起作用,我不会感到惊讶。就是没找到。

这是产生缩放但未旋转输出的核心代码:

## "$molps" is the input ps file read to a variable
## insert the PS "scale" command
$molps = $sf . " " . $sf . " scale\n" . $molps;
$gsopt1 = " -r300 -dGraphicsAlphaBits=4 -dTextAlphaBits=4";
$gsopt1 = $gsopt1 . " -dDEVICEWIDTHPOINTS=$device_width_points";
$gsopt1 = $gsopt1 . " -dDEVICEHEIGHTPOINTS=$device_height_points";
$gsopt1 = $gsopt1 . " -sOutputFile=" . $outfile;
$gscmd = "gs -q -sDEVICE=pnggray -dNOPAUSE -dBATCH " . $gsopt1 . " - ";
system("echo \"$molps\" \| $gscmd");

$device_width_points 和 $device_height_points 是通过获取原始图像大小并应用缩放因子 $sf 来计算的。 我会感谢任何可以向我展示实现这一目标的方法的人。谢谢!

【问题讨论】:

请添加代码示例。 我花了两天时间研究上面提到的各种 gs 命令行选项——大概有一百次迭代。我不确定这是否会有所帮助。但我正在添加核心代码来设置 gs 命令行而不尝试旋转。此代码改编自 Norbert Haider 的“ps2perl.pl”程序。 【参考方案1】:

更好的答案:

您在最初的研究中几乎已经完成了。只需在gs 调用中设置方向:

... | gs ... -dAutoRotatePages=/None -c '<</Orientation 3>> setpagedevice' ...

参见。 discussion of setpagedevice 在红皮书中,ghostscript docs(就在第 6.2 节之前)

原答案:

除了“缩放”之外,您还需要“旋转”和“平移”,不一定要按这个顺序。

大概这些是单页 PostScript 文件?

如果你知道 Postscript 的边界框,以及 png 的尺寸,那么计算必要的变换就不会太费劲了。这将是大约一行代码。您只需要确保将其注入正确的位置即可。

蓝皮书Chapter 6有很多细节 ubc.ca 论文提供了一些插图示例(跳至第 4 页)

可以使用的简单 PostScript 文件。您只需要按某种顺序执行三个 translate、scale、rotate 命令。其余的用于演示正在发生的事情。

%!

% function to define a 400x400 box outline, origin at 0,0 (bottom left)
/box  0 0 moveto 0 400 lineto 400 400 lineto 400 0 lineto closepath  def

box clip % pretend the box is our bounding box 

clippath stroke % draw initial black bounding box

(Helvetica) findfont 50 scalefont setfont % setup a font

% draw box, and show some text @ 100,100
box stroke
100 100 moveto (original) show

% try out some transforms

1 0 0 setrgbcolor % red
.5 .5 scale
box stroke
100 100 moveto (+scaled) show

0 1 0 setrgbcolor % green
300 100 translate
box stroke
100 100 moveto (+translated) show

0 0 1 setrgbcolor % blue
45 rotate
box stroke
100 100 moveto (+rotated) show

showpage

可以像这样将计算出的转换插入gs 命令行:

... | gs ... -c '1 2 scale 3 4 translate 5 6 rotate' -@ ...

【讨论】:

感谢这两个链接。我会研究它们。源文件没有明确的边界框,但使用 -dDEVICE=bbox 选项返回坐标,我尝试按各种顺序缩放并放入 CropBox,但没有任何成功。 (是的,这些是单页文件。) 感谢指点;我想我现在已经舔过了。 -c '&lt;&lt;/Orientation 3&gt;&gt; setpagedevice' 得到了旋转,并且设置 -dDEVICEWIDTHPOINTS 和 -dDEVICEHEIGHTPOINTS 正确地得到了画布大小以匹配缩放的图像大小。【参考方案2】:

感谢 JHNC,我想我现在已经掌握了它,为了后代的利益,这就是有效的方法。 (请支持 JHNC,而不是这个答案。)

## code to determine original size, scaling factor, rotation goes above
my $device_width_points;
my $device_height_points;
my $orientation;
if ($rotation) 
    $orientation = 3;
    $device_width_points = $ytotal_png_pt;
    $device_height_points = $xtotal_png_pt;
 else 
    $orientation = 0;
    $device_width_points = $xtotal_png_pt;
    $device_height_points = $ytotal_png_pt;


my $orientation_string =
    " -dAutoRotatePages=/None -c '<</Orientation " .
        $orientation . ">> setpagedevice'";

## $ps = .ps file read into variable
## insert the PS "scale" command
$ps = $sf . " " . $sf . " scale\n" . $ps;

$gsopt1 = " -r300 -dGraphicsAlphaBits=4 -dTextAlphaBits=4";
$gsopt1 = $gsopt1 . " -dDEVICEWIDTHPOINTS=$device_width_points";
$gsopt1 = $gsopt1 . " -dDEVICEHEIGHTPOINTS=$device_height_points";
$gsopt1 = $gsopt1 . " -sOutputFile=" . $outfile;
$gsopt1 = $gsopt1 . $orientation_string;
$gscmd = "gs -q -sDEVICE=pnggray -dNOPAUSE -dBATCH " . $gsopt1 . " - ";
system("echo \"$ps\" \| $gscmd");

我遇到的一个问题是某些选项显然不能很好地配合使用——例如,我尝试使用 -g 选项设置以像素为单位的输出大小,但在这种情况下,旋转不起作用.改用 DEVICE...POINTS 命令确实有效。

【讨论】:

AutoRotatePages 对除 pdfwrite 系列以外的任何设备都没有影响,因此 PostScript PDF 或 EPS 输出。它不会对任何 PNG 输出设备执行任何操作。

以上是关于Ghostscript -- 将 PS 转换为 PNG、旋转和缩放的主要内容,如果未能解决你的问题,请参考以下文章

ghostscript 将 ps 文件转换为 pcl 丢失托盘设置

通过 Ghostscript 将 PS 文件转换为 PDF/A,色彩空间问题

使用 ghostscript 将 Postscript 转换为文本文件

GHOSTSCRIPT - PS 到 PDF 转换纸张大小

如何使用GhostScript避免tiff上的标头截断。将ps转换为tiff

使用 Ghostscript 指定 PDF 页面大小