2010-07-20 14 views
6

Voici un code pour utiliser SDL avec Haskell pour tracer une ligne diagonale. Je reçois une ligne CYAN quand le RVB devrait être blanc. C'est sur Ubuntu. Est-ce que je fais quelque chose de mal?Pourquoi cette ligne Haskell SDL est-elle cyan alors qu'elle devrait être blanche?

import qualified Graphics.UI.SDL as SDL 
import qualified Graphics.UI.SDL.Primitives as SDLP 

main = do 
    SDL.init [SDL.InitEverything] 
    SDL.setVideoMode 640 480 32 [] 
    SDL.setCaption "My Window" "My Test" 
    surf0 <- SDL.getVideoSurface 
    white <- SDL.mapRGB (SDL.surfaceGetPixelFormat surf0) 255 255 255 
    SDLP.line surf0 0 0 640 480 white 
    SDL.flip surf0 
    eventLoop 
    SDL.quit 
    print "done" 
    where 
    eventLoop = SDL.waitEventBlocking >>= checkEvent 
    checkEvent (SDL.KeyUp _) = return() 
    checkEvent _ = eventLoop 
+1

se fait-il encore avec une ligne verticale, et la peinture tout l'écran? Juste un contrôle de santé mentale pour s'assurer qu'un anti-aliasing fou ne se passe pas ou quelque chose. – luqui

+0

n'est-ce pas un problème avec big-little endian? Vous ne définissez pas la couche alpha alors 255 255 255 0 devient 0 255 255 255 (si vous inversez l'ordre des octets)? – mb14

+0

mb14: NON. Utiliser mapRGB et utiliser 255 255 255 255 fait la même chose. – qrest

Répondre

1

je reçois le même problème sur mon système (pour les deux lignes et autres primitives), et en utilisant le constructeur Pixel directement au lieu de mapRGB semble donner les bonnes couleurs.

Par exemple, si j'importer Graphics.UI.SDL.Color comme SDLC puis let white' = SDLC.Pixel maxBound, je reçois une ligne blanche, comme prévu. Avec SDLC.Pixel 4278190335 (ou 255 * 2^24 + 255, une valeur sensible pour le rouge), j'obtiens une ligne rouge.

Ce n'est clairement pas une solution ou une réponse réelle, mais cela pourrait suggérer quelques points de départ.

Une autre chose étrange: si j'imprimer à la fois votre blanc et le mien comme ceci:

print =<< SDL.getRGBA white (SDL.surfaceGetPixelFormat surf0) 
print =<< SDL.getRGBA white' (SDL.surfaceGetPixelFormat surf0) 
print white 
print white' 

Je reçois ceci:

(255,255,255,255) 
(255,255,255,255) 
Pixel 16777215 
Pixel 4294967295 

Ils ont le même aspect par getRGBA, mais la Pixel réelle les valeurs sont différentes.

2

J'observe le même effet sur Lucid avec ATI HD2400 et pilote radeon (si cela est important). Mais il y a une solution de contournement.

Cet exemple dessine une ligne blanche:

import qualified Graphics.UI.SDL as SDL 
import qualified Graphics.UI.SDL.Primitives as SDLP 

import Control.Applicative ((<$>)) 

main = do 
    SDL.init [SDL.InitEverything] 
    sbase <- SDL.setVideoMode 640 480 24 [] -- draw here 
    -- an ugly hack to get pixel format from an RGB surface: 
    rgbPF <- SDL.surfaceGetPixelFormat <$> SDL.createRGBSurfaceEndian [] 1 1 24 
    white <- SDL.mapRGB rgbPF (-1) (-1) (-1) 
    SDLP.line sbase 0 0 (640-1) (480-1) white 
    SDL.flip sbase 
    eventLoop 
    SDL.quit 
    where 
    eventLoop = SDL.waitEventBlocking >>= checkEvent 
    checkEvent (SDL.KeyDown _) = return() 
    checkEvent _ = eventLoop 

J'accepte que c'est une bidouille horrible, mais il semble que le format » pixel de surface par défaut n'est pas RVB, et en utilisant un format de pixel d'un (?) surface connue pour être RVB aide. Je n'ai pas d'expérience avec SDL, donc je ne peux pas dire quelle est la bonne façon de l'utiliser.

3

Peut-être un hack moins sale (mais probablement dépendant de la plateforme/mise en œuvre):

import GHC.Word 
import Data.Bits 

fi a = fromIntegral a 

rgbColor::Word8→ Word8→ Word8→ Pixel 
rgbColor r g b = Pixel (shiftL (fi r) 24 .|. shiftL (fi g) 16 .|. shiftL (fi b) 8 .|. (fi 255))