我该如何想象 Haskell 中基于像素的渲染?
想象一下一个命令式渲染引擎,它将精灵传输为稍后显示的位图。这在很大程度上依赖于有效地改变所述位图中的各个像素的能力。我该如何用一种没有副作用的语言来做这样的事情呢?我想需要一个完全不同的数据结构?
Imagine an imperative rendering engine that blits sprites to a bitmap that later gets displayed. This heavily relies on the ability to efficiently mutate individual pixels in said bitmap. How would I do such a thing an a language without side effects? I guess a completely different data structure is called for?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以将任何使用可变状态的算法转换为将状态与其一起“串连”的算法。 Haskell 提供了一种执行此操作的方法,使得它仍然感觉像使用状态 Monad 进行命令式编程。
尽管如此,在我看来,基本的位块传输操作可以以更实用的方式完成。您基本上是通过逐像素操作组合两个位图来生成新的位图。这对我来说听起来非常实用。
高质量的命令式代码通常比良好的函数式代码更快,但是如果您愿意放弃一点速度,通常可以以纯函数式风格创建非常好的架构
You can convert any algorithm that uses mutable state into an algorithm that "strings" the state along with it. Haskell provides a way of doing this such that it still feels like imperative programming with the state Monad.
Although, it seems to me that the basic blit operation could be done in a more functional style. You are basically combining two bitmaps to produce a new bitmap via pixel by pixel operation. That sounds very functional to me.
High quality imperative code is often faster than good functional code, but if you are willing to give up a little speed you can normally create very nice architectures in a pure functional style
Haskell 有副作用,您应该在适当的时候使用它们。位于内部循环中的高速 blit 例程(因此对性能至关重要)肯定是适合突变的地方,因此请使用它!您有几个选择:
享受!
Haskell has side effects, and you should use them whenever they're appropriate. A high-speed blit routine that's going to be in your inner loop (and therefore is performance-critical) is certainly one place that mutation is appropriate, so use it! You have a couple of options:
Enjoy!
表示图像的一种自然的功能方式是使用索引函数:
通过这种表示,可以将一个区域从一个图像传输到另一个图像,
如果需要平移或其他变换,可以直接应用于坐标:
这种表示为您提供处理图像点的自然方式。例如,您可以轻松处理非矩形区域,并执行一些技巧,例如将图像插值作为单独的函数,而不是成为常用图像缩放算法的一部分:
在某些情况下,性能可能会受到影响,例如当您位图传输多个图像时化为一,然后用结果进行计算。这会导致每次连续计算时对每个像素进行一系列测试。然而,通过应用记忆化,我们可以暂时将函数表示呈现为数组并将其转换回其索引函数,从而消除连续操作的性能影响。
请注意,记忆也可用于向过程引入并行性。
A natural functional way of representing an image is by using the index function:
With this representation, blitting an area from one image to another would be achieved with
If translation or another transformation is required, it can be directly applied to the coordinates:
This representation gives you natural way of working with image points. You can, for example, easily work with non-rectangular areas, and do tricks like making image interpolation as separate function instead of being part of your usual image scaling algorithms:
The performance might suffer in some cases, such as when you blit multiple images into one and then do calculations with the result. This results in a chain of tests for each pixel for each successive calculation. However, by applying memoization, we can temporarily render the functional representation into an array and transform that back to it's index function, thus eliminating the performance hit for the successive operations.
Note that the memoization can also be used to introduce parallelism to the process.