Skip to content

createRGBSurfaceFrom dependent on system endianness #220

Open
@MichaelMackus

Description

@MichaelMackus

This is most likely simply a documentation issue. The main issue I ran into is that createRGBSurfaceFrom accepts an IOVector of raw pixel bytes. I naively assumed the bytes would be parsed by SDL in the byte order passed in. However, that is not the case, which is due to the fact SDL actually seems to parse these as 32-bit bytes. What this effectively means is the pixel format is different on little endian & big endian machines.

I think it would help to note this in the documentation of the function, since my brain was initially in haskell land and I assumed giving the function a list of RGBA values it would be parsed as an RGBA format.

If anybody wants a more cross-platform way to do this, I believe this should do the trick (it uses JuicyPixels for the underlying image format but that can be easily changed):

import Codec.Picture
import SDL
import System.Endian
import qualified Data.Vector.Storable as V

loadImage :: String -> IO (Image PixelRGBA8)
loadImage f = do
    r <- readImage f
    case r of
        Left  e -> error e
        Right i -> do
            return (convertRGBA8 i)

createSurfaceFromImage :: Image PixelRGBA8 -> IO Surface
createSurfaceFromImage i = do
    pixels <- V.thaw (imageData i)
    let fmt = case getSystemEndianness of
                LittleEndian -> ABGR8888
                BigEndian    -> RGBA8888
    let (w, h) = (fromIntegral (imageWidth i), fromIntegral (imageHeight i))
    createRGBSurfaceFrom pixels (V2 w h) (fromIntegral w*4) fmt

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions