【问题标题】:Image drawing library for Haskell?Haskell 的图像绘图库?
【发布时间】:2010-04-26 03:32:21
【问题描述】:

我正在开发一个用于玩空间游戏的 Haskell 程序:我有一张图表,显示了一群“个人”在玩囚徒困境,但仅限于他们的近邻,并复制最擅长的人的策略。

我已经到了需要绘制世界图像的地步,这就是我遇到问题的地方。两种可能的几何形状很简单:如果每个人有四个或八个邻居,那么我将每个人表示为一个实心正方形(颜色对应于策略)并用这些平铺平面。但是,我也有这样一种情况,即人们有六个邻居(六边形)或三个邻居(三角形)。

那么,我的问题是:有什么好的 Haskell 库可以创建图像并在其上绘制形状?我更喜欢它创建 PNG,但我并不是非常挑剔。我最初使用Graphics.GD,但它只导出绑定到用于绘制点、线、弧、椭圆和非旋转矩形的函数,这对我的目的来说是不够的(除非我想逐个像素地绘制六边形*) .我考虑过使用foreign import,但它证明有点麻烦(部分是因为多边形绘图函数需要gdPoint 结构的数组),并且考虑到我的要求可能会增长,最好使用 in -Haskell 解决方案,而不必与 FFI 混为一谈(尽管如果迫在眉睫,我愿意这样做)。有什么建议吗?

* 实际上,这 也是一种选择;任何有关如何做到这一点的提示也将不胜感激,尽管我认为图书馆会更容易。

编辑:非常感谢大家的建议。不幸的是,我无法获得构建 gtk2hs 所需的所有库,这排除了很多解决方案。由于种种原因,在我尝试了你所有的答案后,未能安装一些库并发现其他人无法做到我想要的,我最终决定只为 libgd 导出更多的 FFI 并改用它。

【问题讨论】:

标签: image graphics haskell


【解决方案1】:

图表看起来很酷,但如果你想避免提交并保持超轻量级,你可以直接生成 svg。从 http://www.lisperati.com/haskell/ 的 Conrad Barski 那里偷东西

type Point     = (Float,Float)
type Color     = (Int,Int,Int)
type Polygon   = [Point]

writePoint :: Point -> String 
writePoint (x,y) = (show x)++","++(show y)++" "

writePolygon :: (Color,Polygon) -> String 
writePolygon ((r,g,b),p) = "<polygon points=\""++(concatMap writePoint p)++"\" style=\"fill:#cccccc;stroke:rgb("++(show r)++","++(show g)++","++(show b)++");stroke-width:2\"/>"

writePolygons :: [(Color,Polygon)] -> String 
writePolygons p = "<svg xmlns=\"http://www.w3.org/2000/svg\">"++(concatMap writePolygon p)++"</svg>"

colorize :: Color -> [Polygon] -> [(Color,Polygon)] 
colorize = zip.repeat

rainbow@[red,green,blue,yellow,purple,teal] = map colorize [(255,0,0),(0,255,0),(0,0,255),(255,255,0),(255,0,255),(0,255,255)]

t0 = writeFile "tut0.svg" $ writePolygons (blue [[(100,100),(200,100),(200,200),(100,200)],[(200,200),(300,200),(300,300),(200,300)]])

hexagon c r = translateTo c basicHexagon where
  basicHexagon =  top ++ (negate r, 0):bottom 
  top          =  [(r,0),(r * cos 1,(r * sin 1)),(negate (r * cos 1), r * (sin 1))]
  bottom       =  map (\(x,y)->(x,negate y)) (reverse top)

translateTo (x,y) poly = map f poly where f (a,b)= ((a+x),(b+y))

t1 = writeFile "t1.svg" $ writePolygons (blue [hexagon (100,100) 50] )

hexField r n m = let 
     mkHex n = hexagon (1.5*n*(r*2),(r*2)) r
     row n = map mkHex [1..n]
     aRow = row n
  in concat [map (offset (r*x)) aRow |x<-[1..m]]

offset r polys = map (oh r) polys where
  oh r pt@(x,y) = (x+(1.5*r),y+(r*sin 1))

t2 = writeFile "t2.svg" $ writePolygons (blue $ hexField 50 4 5 )

运行 t2 并将文件加载到 Firefox 或其他支持 svg 的程序中。

t2.svg ,exported png http://img30.imageshack.us/img30/2245/93715707.png

【讨论】:

    【解决方案2】:

    我以前用过 HOpenGL,但是 问题是(据我所知) 它不能渲染到文件,但只能 屏幕;相同(再次,至于 我可以告诉)似乎是真的 SDL 和 Wx。我会看看开罗, 不过。

    由于某种原因,我无法回复这篇文章,所以我必须引用它。您对 GL 和 SDL 不正确,您可以制作屏幕外表面/缓冲区或渲染到纹理。这些库不需要这样的函数(也没有多大意义),因为您可以通过访问缓冲区中的像素并将其写出自己来很容易地做到这一点,即使使用屏幕缓冲区也可以访问像素数据。

    就在前几天,我向某人展示了如何使用 Haskell SDL 绑定来做到这一点:

    http://hpaste.org/fastcgi/hpaste.fcgi/view?id=25047

    使用可以写入 .PNG 文件的库,它们很可能会获取一个指向像素缓冲区的原始指针,您可以从 SDL/GL 获取该原始指针,或者将其复制为库需要的格式。

    我刚刚找到一个Haskell binding for the library DevIL,它可以输出.PNG 文件。查看名为writeImageFromPtr的函数

    【讨论】:

    • 哦,哇——我没想过要以这种方式解决问题!这看起来很有希望(特别是因为 gtk 安装失败);我会安装它,看看我能不能让它工作。
    • 我忘了再提一件事,如果你要访问渲染到屏幕缓冲区中的像素数据,你可能应该将整个缓冲区blit(复制)到系统内存中的缓冲区中,因为通常,前/后屏幕缓冲区位于 VRAM 中,您需要锁定缓冲区/表面,您不想通过长时间运行的操作阻塞 GPU。另请注意,SDL 可以选择在系统内存中创建屏幕表面。
    • 如果你这样走,你应该使用OpenGL的访问屏幕。 SDL 只会认为它是空的。见hackage.haskell.org/packages/archive/OpenGL/latest/doc/html/…
    • 嗨,hpaste.org 链接似乎不再有任何代码。有人可以链接到直接写入 sdl 缓冲区的解决方案吗?
    【解决方案3】:

    如果您想生成 PNG,Cairo 是一个不错的选择。 Wumpus 看起来也很有希望,尽管我从未使用过它。如果您只需要在屏幕上看到它,graphics-drawingcombinators 是一个简单的 OpenGL 接口,只需几行代码即可完成您需要的操作(请参阅发行版中的 example.hs)。

    【讨论】:

    • 我肯定会看看 Cairo(并安装 gtk2hs...)和 Wumpus,因为我确实需要将图像保存到文件中。但是,如果我以后需要做 HOpenGL 类型的东西,graphics-drawingcombinators 看起来真的很酷(虽然,仅供参考,你的链接再次指向wumpus-core)。
    【解决方案4】:

    【讨论】:

      【解决方案5】:

      有什么好的 Haskell 库可以用来创建图像并在其上绘制形状?

      你有很多选择,在我看来以下都是used for games

      这些是最常见的,您可以根据功能/熟悉程度进行选择。

      【讨论】:

      • 我以前用过HOpenGL,但问题是(据我所知)它不能渲染到文件,只能渲染到屏幕上; SDL 和 Wx 似乎也是如此(再次,据我所知)。不过,我会去开罗看看。
      猜你喜欢
      • 2011-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      • 1970-01-01
      相关资源
      最近更新 更多