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

时间:2019-02-11 18:36:54

标签: png ghostscript postscript

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

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

我已经在网上搜索并花了几天的时间来尝试修改我发现的示例,但是我没有尝试过(a)旋转,(b)调整大小,(c)保持宽高比的组合和(d)避免削波。

我确实找到了一个向后记流中注入“缩放”命令的示例,并且在保持纵横比的同时将图像缩放到所需大小似乎效果很好。但是我找不到旋转尺寸调整后的图像的方法,以使例如601 x 792点(2504 x 3300像素)的后记输入变为800 x 608像素png输出。

我正在寻找可以传递给gs命令行的ghostscript / postscript fu。

我尝试使用-dFIXEDMEDIA,-dFitPage,-dAutoRotatePages = / None或/ All,-c“ <> setpagedevice”的各种组合的gs命令行,更改-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来计算的。 我将感谢任何能够向我展示实现此目标的方法的人。谢谢!

2 个答案:

答案 0 :(得分:1)

更好的答案:

您几乎在最初的研究中就掌握了它。只需在gs调用中设置方向:

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

cf。 《红皮书》中的discussion of setpagedeviceghostscript 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' -@ ...

答案 1 :(得分:1)

多亏了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命令起作用了。