4

我正在使用sdl2@2.2.0sdl2-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、缩放/调整大小并将其栅格化为 aSDL.SurfaceSDL.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)
                        );

您必须对static_cast<void *>传递给的图像数据执行 a SDL_CreateRGBSurfaceFrom。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:

我现在有一个正在运行的例子。但是,渲染结果还不正确。

这个SVG

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
4

1 回答 1

2

我没有用真实的代码测试过,但希望它在正确的轨道上:

renderSvgDocument为您提供IO (Image PixelRGBA8)来自 JuicyPixels 图像库的结果类型。

imageData给你一个 ( Storable)Vector (PixelBaseComponent PixelRGBA8)我猜是Vector Word8在追逐所有类型之后。

thawunsafeThaw(阅读文档以获取重要的安全信息)为您获取 immutable 的可变副本(或视图,对于不安全的变体)Vector

于 2017-08-30T01:26:16.570 回答