流畅的 PostScript 动画

发布于 2024-12-19 11:23:49 字数 1651 浏览 2 评论 0原文

我想在 PostScript 中顺利运行动画。为了看看我想要什么,让我直接切换到 PostScript。调用 Ghostscript,

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。看 此页面。也许现在有一些更好的想法?

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

  • 从语言层面应该如何看待动画?我相信,最好的方法是将每个框架视为单个页面。使用copypage可以轻松实现增量更改。遗憾的是,copypage 的语义仅存在于级别 1 和 2 中。在级别 3 中,copypage 的含义更改为 showpage。很多年前,我做了对 Ghostscript 进行了一些修改来延迟所有可见更改最多可达 copypageshowpage。通过这种方式,包含更改区域的单个 XCopyArea 在服务器(即显示器)上本地执行。

  • 应该如何同步视觉显示上的实际变化以避免所描述的图形中不存在的伪影?您看到的不规则闪烁并不是 PostScript 的特权,它似乎存在于我迄今为止见过的任何双缓冲系统中。只要尝试在您认为合适的任何系统中对此进行编程即可。

进一步编辑:

要获得正确的语言级别,即级别 1 或 2(对于 Ghostscript):

systemdict /.setlanguagelevel known {2 .setlanguagelevel} if

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

I would like to run animations in PostScript smoothly. To see what I want, let me switch to PostScript directly. Call ghostscript, and

200 dup scale .5 setgray 0 0 3 3 rectfill

We have now a gray square.

0 setgray 0 1 3 1 rectfill

With a black stripe in it. We will now fill that stripe, one time white
and black in succession:

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

You will see now some flickering of black and white rectangles that
are smaller than the original black stripe. Ideally, we would see
the original grey square. Or almost. Where can I get such functionality today?

To see a more interesting animation sequence searching for magic
squares of size 5:

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

A couple of years ago I did try to address these issues. But it never went into ghostscript or Xfree. See
this page. Maybe there are some better ideas now?

Edit: After reading the responses so far, let me clarify one issue here. Essentially, there are two independent issues in this question:

  • How should an animation be viewed from the language level? I believe, the best way is to view each frame as a single page. With copypage incremental changes can be realized with low effort. Sadly, that semantics of copypage is only present in Level 1 and 2. In Level 3, the meaning of copypage changed to showpage. I did - many years ago - a little modification to ghostscript to delay all visible changes up to copypage or showpage. In this manner, a single XCopyArea containing the changed area is performed locally on the server (that is, the display).

  • How should actual changes on the visual display be synchronized to avoid artefacts that where not present in the graphics described? The irregular flicker you see is not a privilege of PostScript, it seems to be present in any double-buffered system I have seen so far. Just try to program this in whatever system you see fit.

Further edit:

To get the right language level, that is level 1 or 2 do (for ghostscript):

systemdict /.setlanguagelevel known {2 .setlanguagelevel} if

Edit: I am adding this comment to may attract some new contributors.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

九公里浅绿 2024-12-26 11:23:50

我们在 comp.lang 上的这个帖子中探讨了其中一些问题。后记

自 Level 2 标准发布以来,Postscript 就是一种垃圾收集语言。您可以使用片段 -2 vmreclaim 禁用用户对象的收集,但它并没有多大作用。您可以通过使用 -dNOGC 选项调用来禁用所有 Ghostscript 垃圾收集。这应该有助于防止图像部分停顿和吐出。

Ghostscript 有一个名为 flushpage 的非标准运算符,它可以将渲染与执行。这有助于确保所有内容在消失之前都被看到

<前><代码>-刷新页面-
在显示器上,刷新任何缓冲的输出,以便保证
显示在屏幕上;在打印机上,没有影响

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


/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 

围绕flushpage 的where 保护允许您将相同的代码发送到ghostscript 以外的解释器(如打印机)。

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

We explored some of these issues in this thread on comp.lang.postscript.

Since the release of the Level 2 standard, Postscript is a garbage-collected language. You can disable collection of user objects with the fragment -2 vmreclaim, but it doesn't accomplish much. You can disable ALL ghostscript garbage collection by invoking with the -dNOGC option. This should help prevent stalling and spitting with parts of the image.

Ghostscript has a non-standard operator called flushpage, which synchronizes the rendering with the execution. This helps make sure that everything is seen before it's gone.

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

And for timing control, there doesn't seem to be a better way than simple busy-waiting.


/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 

The where guards around flushpage allow you to send the same code to interpreters other than ghostscript (like a printer).

If you had an actual Display Postscript server, you could use the wait operator instead of busy-waiting.

没企图 2024-12-26 11:23:50

虽然我喜欢(并赞成)@luserdroog 的答案,但我不认为 Postscript 应该以这种方式用于动画 - 我宁愿使用某种可以运行小部件或显示专为实时显示和用户交互而设计的元素的语言- 这不是后记或鬼记的情况。

不过,我认为使用 postscript 来达到渲染目的会很好 - 只需在每次修改图像后渲染一个页面,并使用外部程序将不同的页面组装为动画帧。
甚至可能使用 postscript 作为渲染引擎,用另一种语言调用 Ghostscript 来实时渲染每个帧。一个很好且易于使用的多媒体框架可以做到这一点,例如带有 Pygame 模块的 Python 语言。

这是一个使用“纯 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 系统)

Pygame 的绘图 API 比 postscript 差很多 - 如果你需要的不仅仅是矩形
(如 bezies、缩放、旋转和剪切坐标系等),方法是使用 Cairo + python + 一些显示库(可能是 pygame、GTK+ 或 qt)。 Cairo是一个继承自postscript方式的2D绘图库。 - 或者,正如我上面所说,使用 Python 驱动 Ghostscript 外部进程,让它生成一个 rle 压缩图像文件到 stdout 或 ramdrive,并使用 python + pygame 逐帧读取和显示该图像。

另一种选择是使用 HTML5 的 Canvas,并在 Javascript 中完成所有操作,可在浏览器上查看。 HTML5的Canvas也继承了Postscript的绘制方式。

Although I like (and upvoted) @luserdroog's answer, I don't believe Postscript should be used for animations on this way - I'd rather use some language that can run widgets or display elements that are designed for real time display and user interation - that is not the case of postscript or ghostscript.

I think it would be nice, though, use postscript for aimations for rendering purposes - just rendering a page after each modification on the image, and using an external program to assemble the different pages as animation frames.
Maybe even using postscript as a rendering engine, with the process in another language calling ghostscript to render each frame in realtime. A nice and easy to use multimedia framework to do that could be for example, the Python language with the Pygame module.

Here is a short example using "pure 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()

To execute this, you have to have Python and Pygame (from http://pygame.org - there are ready packages on most linux systems for that)

Pygame's drawing API is much poorer than postscript - if you need more than rectangles
(like bezies, scaling, rotating and shearing the coordinate system, and so on), the way to go is to use Cairo + python + some display library (which might be pygame, GTK+ or qt) . Cairo is a 2D drawing library that inherits from the postscript way. - or, as I said above, to drive a ghostscript external process using Python, having it generating a rle compressed image file to stdout or a ramdrive, and that image read and displayed frame by frame using python + pygame.

Another option is to use HTML5's Canvas, and do everything in Javascript, viewable on a browser. HTML5's Canvas also inherits the Postscript way of drawing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文