平滑的PostScript动画

7
我希望能够在PostScript中流畅地运行动画。为了看到我想要的效果,让我直接切换到PostScript。调用ghostscript,并保留HTML标签。
200 dup scale .5 setgray 0 0 3 3 rectfill

我们现在有一个灰色的正方形。
0 setgray 0 1 3 1 rectfill

在其中有一条黑色条纹。我们现在将交替填充该条纹,先白色再黑色:

{1 setgray 0 1 3 1 rectfill 0 setgray 0 1 3 1 rectfill} loop

您现在会看到一些黑白矩形的闪烁,它们比原来的黑条小。理想情况下,我们应该看到原始的灰色正方形。或者几乎是这样。今天在哪里可以获得这样的功能?

要查找大小为5的幻方并查看更有趣的动画序列:

wget http://www.complang.tuwien.ac.at/ulrich/gupu/l5.eps.gz
zcat l5.eps.gz | ghostscript -

几年前我曾试图解决这些问题。但它从未被整合到ghostscript或Xfree中。请参见this page。也许现在有更好的想法了?

编辑:阅读到目前为止的回复后,让我澄清一个问题。本质上,这个问题有两个独立的问题:

  • 动画在语言层面上应该如何被视为?我认为,最好的方法是将每一帧视为单独的页面。通过使用 copypage 可以实现低成本的增量变化。遗憾的是,在第 3 级中,copypage 的语义已经改变为 showpage。很多年前,我对 ghostscript 进行了 小修改,延迟了所有可见变化直到 copypageshowpage。这样,一个包含更改区域的单个 XCopyArea 就可以在服务器(即显示器)上进行本地执行。

  • 如何同步实际的视觉变化,以避免在描述图形时不存在的伪影?你看到的不规则闪烁并不是 PostScript 的特权,它似乎存在于我所见过的任何双缓冲系统中。只需尝试在适当的系统中编写此程序即可。

进一步编辑:

为了获得正确的语言级别,即1级或2级,请执行以下操作(对于Ghostscript):
systemdict /.setlanguagelevel known {2 .setlanguagelevel} if

编辑:我添加了这条评论,可能会吸引一些新的贡献者。


对我来说,如果你想从一系列白色和黑色样本中获得灰色的“效果”,它需要与显示器的刷新率同步。在60hz下,你最多只需要每个样本2个“帧”,30hz略高于视觉暂留阈值。 - luser droog
这只是一个测试示例,其中清楚地显示了什么应该可见,什么不应该可见。没有人想以那种方式绘制灰色(25年前在ATARI上这样做很流行...)。今天有趣的是查看像上面(l5.eps)这样的离散动画,并且不会看到不属于动画的伪影。请看一下:它向您展示了CLPFD程序如何通过系统地枚举所有可能性来找到魔方的解决方案。 - false
1
最近有一个关于在“批处理”模式下使用PostScript和动画的讨论线程。 - luser droog
2个回答

4

我们在这个comp.lang.postscript线程中探讨了其中一些问题。

自Level 2标准发布以来,Postscript成为了一种垃圾回收语言。您可以使用片段-2 vmreclaim禁用用户对象的收集,但这并没有什么作用。您可以通过使用-dNOGC选项来禁用所有ghostscript垃圾回收。这应该有助于防止图像的某些部分停顿和吐出。

Ghostscript有一个非标准运算符称为flushpage,它将呈现与执行同步。这有助于确保在消失之前已经看到了一切。

- flushpage -
On displays, flushes any buffered output, so that it is guaranteed to
show up on the screen; on printers, has no effect

对于时间控制,似乎没有比简单的忙等待更好的方法。


/smallpause {
    /flushpage where{pop flushpage}if
    50 sleep } def
/pagepause {
    /flushpage where{pop flushpage}if
    1000 sleep } def

/sleep {
    usertime add {
        10 {
            1 100000 div pop %busy
            .1 sin 257 cos atan pop %busy busy
        } repeat
        dup usertime le {exit}if
    } loop pop
} def 
< p > where 保护 flushpage 周围的代码,使您可以将相同的代码发送到除 ghostscript(如打印机)之外的解释器。

如果您有一个实际的 Display Postscript 服务器,您可以使用 wait 运算符而不是忙等待。


这里有两个问题。应该看到什么?以及如何执行与显示器的交互?你对前者感兴趣,而我对后者更感兴趣。我认为flushpage不是一个好的选择。copypage(即只有1级和2级语义)是干净、逻辑清晰的方式。 - false
这很有道理。我从copypage没有得到想要的结果。它总是执行erasepage,而我不想要这个。我可能需要升级我的ghostscript安装。 - luser droog
不行!你必须将语言级别设置为1或2。 - false
我在文档中找不到它!你如何设置语言级别? - luser droog
1
我把它放在我的问题末尾:以前是这样的:systemdict /.setlanguagelevel known {2 .setlanguagelevel} if - false

3
虽然我喜欢(并点赞)@luserdroog的答案,但我不认为应该以这种方式使用Postscript进行动画制作 - 我宁愿使用一些可以运行小部件或显示为实时显示和用户交互而设计的元素的语言 - 这不是PostScript或Ghostscript的情况。
我认为很好,可以使用Postscript进行渲染目的的动画 - 仅在图像每次修改后呈现页面,并使用外部程序组合不同的页面作为动画帧。 甚至可以使用Postscript作为渲染引擎,使用另一种语言中的进程调用ghostscript以实时呈现每个帧。一个不错且易于使用的多媒体框架可以是Python语言与Pygame模块。
以下是一个使用“纯Python + Pygame”的简短示例。
#! /usr/bin/env python
# coding: utf-8

import pygame

size = 640,480 #(in pixels)

# multiplying factor so that the whole image is 5 units across
factor = size[0] / 5.0

# Inits pygame drawing window
screen = pygame.display.set_mode(size)

# Rectangle drawing function that scales drawing using the factor above
def draw_rect(color, rect):
    new_rect = [int (r * factor) for r in rect]
    return pygame.draw.rect(screen, color, new_rect)

def main():
    draw_rect((128,128,128), (0, 0, 3, 3))
    colors = ((255,255,255), (0,0,0))
    color_index = 0
    while True:
        draw_rect(colors[color_index], (0, 1, 3, 1))
        pygame.display.flip()
        color_index = 1 - color_index
        pygame.time.delay(50) # in miliseconds

try:
    main()
finally:
    pygame.quit()

要执行此操作,您必须拥有Python和Pygame(从 http://pygame.org - 大多数Linux系统都有准备好的软件包)。
如果您需要更多于矩形的绘制功能(例如bezies、缩放、旋转和剪切坐标系等),则使用Cairo+Python+一些显示库(可能是Pygame、GTK+或qt)是最佳选择。Cairo是一个2D绘图库,延续了postscript的绘图方式,或者如上所述,使用Python驱动ghostscript外部进程,使其生成一个rle压缩的图像文件到stdout或ramdrive,并且使用python + pygame逐帧读取和显示该图像。
另一个选择是使用HTML5的Canvas,在Javascript中完成所有操作,可以在浏览器中查看。HTML5的Canvas也继承了Postscript的绘图方式。

1
我从1990年开始使用PostScript进行动画制作。到目前为止,我还没有看到过其他任何一种编程语言能够具备相同的2D功能。顺便问一下,你有尝试在其他框架中编写原始程序吗?如果有的话,我很想看看是否有任何系统能够准确地显示这样的图形。 - false
只是为了让事情清楚明白:画一个大小为3x3的灰色正方形,在其中绘制一个3x1的矩形条纹,始终将该矩形的颜色从白色更改为黑色。 - false
谢谢!关键似乎是 pygame.display.flip()。您能否将睡眠去掉并告诉我结果呢? (我在Karmic Ubuntu上尝试了无数次安装pygame,但都不成功。) - false
没有“delay”调用,我看到白色/黑色/灰色的超快闪烁,在一些帧中,白色内部有黑色条纹 - 但这里的效果更多地与我运行没有任何加速的X11驱动程序有关 - 使用50ms延迟,我可以得到明确定义的黑色和白色。 - jsbueno
我担心的是,理论上,pygame.display.flip()copypage可以与X驱动程序检查绘制操作是否可以立即完成,或者等待直到可能为止。这在大约10年前的XFree mod中已经实现了 - 如果今天也有这样的功能就太好了。 - false
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接