【发布时间】:2017-08-29 06:05:26
【问题描述】:
我正在使用sdl2@2.2.0 和sdl2-image@2.0.0。我想画一个 SVG 图像,但是 sdl2-image 不支持这种格式(见https://www.libsdl.org/projects/SDL_image/):
SDL_image 是一个图像文件加载库。
它将图像加载为 SDL 表面和纹理,并支持以下格式:BMP、GIF、JPEG、LBM、PCX、PNG、PNM、TGA、TIFF、WEBP、XCF、XPM、XV
如何加载 SVG、缩放/调整大小并将其栅格化为 SDL.Surface 或 SDL.Texture?
编辑:
在 C++ 中,您可以使用 nanosvg 库:
NSVGimage * svg_image = nsvgParseFromFile(filepath.c_str(), "px", 96.0);
std::vector<Uint8> img_data;
img_data.resize(width * height * 4);
NSVGrasterizer * rasterizer = nsvgCreateRasterizer()
nsvgRasterize(rasterizer,
svg_image, 0,0,1,
img_data.data(),
width, height,
width * 4);
SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(
static_cast<void *>(img_data.data()),
width, height,
32, // depth
4 * width, // pitch
0x000000FF, // red mask
0x0000FF00, // green mask
0x00FF0000, // blue mask
0xFF000000 // alpha mask (alpha in this format)
);
您必须对传递给SDL_CreateRGBSurfaceFrom 的图像数据执行static_cast<void *>。 Haskell 的 SDL.createRGBSurfaceFrom(sdl2 版本 2.2.0)需要 Data.Vector.Storable.Mutable.VectorIO Word8 作为图像数据。
我找到了一个很有前途的库rasterific-svg
此包可以将 SVG 渲染为图像或将其转换为 PDF。
您可以使用drawingOfSvgDocument 或renderSvgDocument 进行渲染。但是,我不知道如何将任一结果转换为Data.Vector.Storable.Mutable.VectorIO Word8。
编辑 2:
我现在有一个正在运行的example。但是,渲染结果还不正确。
这个SVG
呈现为
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Codec.Picture
import Codec.Picture.Types
import Data.Vector.Storable.Mutable (IOVector)
import Data.Vector.Generic (thaw)
import Graphics.Rasterific.Svg
(loadCreateFontCache, renderSvgDocument)
import Graphics.Svg (loadSvgFile)
import Data.Function (fix)
import Data.Word (Word8)
import Control.Monad as CM
import qualified Data.Vector.Generic.Mutable as GM
import Data.Vector.Storable (Vector)
import qualified Data.Vector.Storable as V
import Foreign.C.Types (CInt)
import qualified SDL
import SDL.Vect (Point(P), V2(V2), V4(V4))
import Control.Concurrent (threadDelay)
import SDL (($=))
import Paths_render_svg_in_sdl2_haskell (getDataFileName)
screenWidth, screenHeight :: CInt
(screenWidth, screenHeight) = (1280, 720)
-- SDL dependency: sudo apt-get install libsdl2-dev
main :: IO ()
main = do
SDL.initialize [SDL.InitVideo, SDL.InitTimer, SDL.InitEvents]
-- ensure render quality
SDL.HintRenderScaleQuality $= SDL.ScaleLinear
do renderQuality <- SDL.get SDL.HintRenderScaleQuality
CM.when (renderQuality /= SDL.ScaleLinear) $
putStrLn "Warning: Linear texture filtering not enabled!"
window <-
SDL.createWindow
"Load and render SVG"
SDL.defaultWindow
{ SDL.windowPosition = SDL.Centered
, SDL.windowInitialSize = V2 screenWidth screenHeight
}
SDL.showWindow window
renderer <-
SDL.createRenderer
window
(-1)
SDL.RendererConfig
{ SDL.rendererType = SDL.AcceleratedVSyncRenderer
, SDL.rendererTargetTexture = True
}
SDL.rendererDrawColor renderer $= V4 maxBound maxBound maxBound maxBound
SDL.clear renderer
renderSvgExample renderer
SDL.present renderer
threadDelay 2000000
SDL.destroyRenderer renderer
SDL.destroyWindow window
SDL.quit
renderSvgExample :: SDL.Renderer -> IO ()
renderSvgExample renderer = do
mimage <- getDataFileName "thumbs-up.svg" >>= loadSVGImage
case mimage of
Nothing -> putStrLn "Image convertion failed."
(Just image) -> do
let surfaceSize :: V2 CInt
surfaceSize = V2 screenWidth screenHeight
surface <- createSurfaceFromSVG image surfaceSize
texture <- SDL.createTextureFromSurface renderer surface
SDL.freeSurface surface
let source = SDL.Rectangle (P $ V2 0 0) surfaceSize
dest = SDL.Rectangle (P $ V2 0 0) surfaceSize
angle = 0.0
center = Nothing
flipNone = V2 False False
SDL.copyEx
renderer
texture
(Just source)
(Just dest)
angle
center
flipNone
SDL.destroyTexture texture
createSurfaceFromSVG :: Image PixelRGBA8 -> V2 CInt -> IO SDL.Surface
createSurfaceFromSVG image surfaceSize = do
let rawImageData :: Vector Word8
rawImageData = imageData image
imWidth :: Int
imWidth = imageWidth image
pitch :: CInt
pitch = fromIntegral imWidth
mutableVector <- convertToMutableVector rawImageData
SDL.createRGBSurfaceFrom mutableVector surfaceSize pitch SDL.RGBA8888
convertToMutableVector :: Vector Word8 -> IO (IOVector Word8)
convertToMutableVector= thaw
loadSVGImage :: FilePath -> IO (Maybe (Image PixelRGBA8))
loadSVGImage filepath = do
mdoc <- loadSvgFile filepath
case mdoc of
Nothing -> return Nothing
Just doc -> do
cache <- loadCreateFontCache "fonty-texture-cache"
(finalImage, _) <- renderSvgDocument cache Nothing 96 doc
return $ Just finalImage
【问题讨论】:
-
你试过什么? “sdl2-image 不支持这种格式”是什么意思?如果您认为这些库应该是可能的,我猜您可以编写相应的 C 程序 - 如果是这样,请随意包含该程序。
-
我添加了一个使用 nanosvg 的 C++ 解决方案,并引用了 SDL2 Image 支持的图像格式。
-
投票结束,因为这是一个图书馆推荐问题,这与 SO 无关。只需谷歌“Haskell SVG 渲染器”,您应该会找到一些选项。
-
我被要求提供另一种语言的示例。我的示例是在 C++ 中,需要另一个库 nanosvg。您必须对图像数据执行
static_cast<void *>。 Haskell 的SDL.createRGBSurfaceFrom期望Data.Vector.Storable.Mutable.VectorIO Word8作为图像数据。不知道有无库如何获取这种类型的图片数据。
标签: haskell svg sdl-2 haskell-stack haskell-sdl