Sto scrivendo un programma Haskell che disegna big maps dai file mondiali Knytt Stories. Io uso il pacchetto friday
per creare file di immagine e ho bisogno di comporre i molti strati grafici che ho assemblato dagli spritesheets. In questo momento, io uso la mia funzione di brutto per questo:Il pacchetto `Friday` è molto lento
import qualified Vision.Primitive as Im
import qualified Vision.Image.Type as Im
import qualified Vision.Image.Class as Im
import Vision.Image.RGBA.Type (RGBA, RGBAPixel(..))
-- Map a Word8 in [0, 255] to a Double in [0, 1].
w2f :: Word8 -> Double
w2f = (/255) . fromIntegral . fromEnum
-- Map a Double in [0, 1] to a Word8 in [0, 255].
f2w :: Double -> Word8
f2w = toEnum . round . (*255)
-- Compose two images into one. `bottom` is wrapped to `top`'s size.
compose :: RGBA -> RGBA -> RGBA
compose bottom top =
let newSize = Im.manifestSize top
bottom' = wrap newSize bottom
in Im.fromFunction newSize $ \p ->
let RGBAPixel rB gB bB aB = bottom' Im.! p
RGBAPixel rT gT bT aT = top Im.! p
aB' = w2f aB; aT' = w2f aT
ovl :: Double -> Double -> Double
ovl cB cT = (cT * aT' + cB * aB' * (1.0 - aT'))/(aT' + aB' * (1.0 - aT'))
(~*~) :: Word8 -> Word8 -> Word8
cB ~*~ cT = f2w $ w2f cB `ovl` w2f cT
aO = f2w (aT' + aB' * (1.0 - aT'))
in RGBAPixel (rB ~*~ rT) (gB ~*~ gT) (bB ~*~ bT) aO
Semplicemente alpha-compositi uno strato di fondo e uno strato superiore, in questo modo:
Se il livello “basso” è una texture, sarà loopata orizzontalmente e verticalmente (da wrap
) per adattarsi alle dimensioni del livello superiore.
Rendering di una mappa richiede molto, molto più tempo del dovuto. Il rendering della mappa per il mondo predefinito incluso nel gioco richiede 27 minuti allo -O3
, anche se il gioco stesso può rendere chiaramente ogni schermata separata in meno di un paio di millisecondi. (L'uscita esempio più piccola ho linkato sopra vedi sopra richiede 67 secondi, anche troppo a lungo.)
Il profiler (uscita è here) dice che il programma spende circa il 77% del suo tempo in compose
.
Questo taglio sembra un buon primo passo. Sembra un'operazione molto semplice, ma non riesco a trovare una funzione nativa in friday
che mi consente di farlo. Presumibilmente GHC dovrebbe essere bravo a far crollare tutto il materiale fromFunction
, ma non so cosa sta succedendo. O il pacchetto è semplicemente super lento?
Here’s the full, compileable code.
È possibile utilizzare l'opzione di profilatura '-auto-all' per scavare un po 'più in profondità nella' comporre' e vedere cosa sta impiegando il tempo? – crockeea
Questo ti dice qualcosa? https://bpaste.net/raw/cb2454d6fbc6 – Lynn
[Qui] (https://gist.github.com/lynn/504e0712b5dd8c13f953) è il codice, per il confronto – Lynn