2010-07-20 6 views
6

Di seguito è riportato un codice per utilizzare SDL con Haskell per disegnare una linea diagonale. Ottengo una linea CYAN quando l'RGB deve essere chiaramente bianco. Questo è su Ubuntu. Sto facendo qualcosa di sbagliato?Perché questa linea Haskell SDL è ciano quando dovrebbe essere bianca?

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

accade ancora con una linea verticale, e con la pittura l'intero schermo? Solo un controllo di integrità per assicurarsi che qualche pazzo anti-aliasing non stia succedendo o qualcosa del genere. – luqui

+0

non è un problema con big-little endian? Non si imposta il canale alfa in modo che 255 255 255 0 diventi 0 255 255 255 (se si inverte l'ordine dei byte)? – mb14

+0

mb14: NO. Usare mapRGB e usare 255 255 255 255 fa la stessa cosa. – qrest

risposta

1

ottengo lo stesso problema sul mio sistema (per entrambe le linee e altre primitive), e utilizzando il costruttore Pixel direttamente invece di mapRGB sembra dare i colori corretti.

Ad esempio, se importare Graphics.UI.SDL.Color come SDLC e quindi let white' = SDLC.Pixel maxBound, ottengo una linea bianca, come previsto. Con SDLC.Pixel 4278190335 (o 255 * 2^24 + 255, un valore ragionevole per il rosso), ottengo una linea rossa.

Questo chiaramente non è una soluzione o una risposta reale, ma potrebbe suggerire alcuni punti di partenza.

Un'altra cosa strana: se stampo sia il bianco e la mia in questo modo:

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

ottengo questo:

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

Così hanno lo stesso aspetto tramite getRGBA, ma l'attuale Pixel i valori sono diversi

2

Osservo lo stesso effetto su Lucid con ATI HD2400 e driver radeon (se questo è importante). Ma c'è una soluzione.

questo esempio disegna una linea bianca:

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 

accetto che questo è un brutto hack, ma sembra che il formato dei pixel superficie di default' non è RGB, e utilizzando un formato di pixel di un (?) la superficie nota per essere l'RGB aiuta. Non ho esperienza con SDL, quindi non posso dire quale sia il modo giusto per usarlo.

3

Forse un hack meno sporca (anche se probabilmente la piattaforma/carico di attuazione):

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))