module Graphics.Rendering.Rect.Image( Atlas, buildAtlas, Texture(..), atlasLookup) where import qualified Data.HashMap.Lazy as HM import Data.Text (Text) import Codec.Picture (DynamicImage(..), Image(..), PixelRGBA8(..), generateImage) import Codec.Picture.Types (promoteImage, dynamicMap) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad (forM) import Data.Maybe (fromMaybe) import Typograffiti.GL import Graphics.GL.Core32 import Graphics.GL.Types import Graphics.GL.Ext.EXT.Cmyka import Graphics.GL.Ext.SGIX.Ycrcb import Graphics.GL.Compatibility32 import Data.Vector.Storable (unsafeWith, unsafeCast) import Foreign.Ptr (castPtr) import Foreign.Marshal.Array (allocaArray, peekArray) data Atlas = Atlas { unAtlas :: HM.HashMap Text GLuint } buildAtlas :: MonadIO m => (Text -> IO DynamicImage) -> [Text] -> m Atlas buildAtlas cb srcs = do -- TODO Merge textures into an actual atlas. let len = length srcs textures <- liftIO $ allocaArray (toEnum len) $ \ptr -> do glGenTextures (toEnum len) ptr peekArray len ptr imgs <- liftIO $ forM srcs cb forM (zip textures imgs) $ \(texture, dyn) -> do let img = dynamicMap (unsafeCast . imageData) dyn let (format, word) = glFormat dyn liftIO $ glBindTexture GL_TEXTURE_2D texture liftIO $ unsafeWith img $ glTexImage2D GL_TEXTURE_2D 0 GL_RGBA (toEnum $ dynamicMap imageWidth dyn) (toEnum $ dynamicMap imageHeight dyn) 0 format word return $ Atlas $ HM.fromList $ zip srcs textures data Texture = Texture GLuint atlasLookup :: Text -> Atlas -> Texture atlasLookup key = Texture . fromMaybe 0 . HM.lookup key . unAtlas glFormat (ImageY8 _) = (GL_LUMINANCE, GL_UNSIGNED_BYTE) glFormat (ImageY16 _) = (GL_LUMINANCE, GL_UNSIGNED_SHORT) glFormat (ImageY32 _) = (GL_LUMINANCE, GL_UNSIGNED_INT) glFormat (ImageYF _) = (GL_LUMINANCE, GL_FLOAT) glFormat (ImageYA8 _) = (GL_LUMINANCE_ALPHA, GL_BYTE) glFormat (ImageYA16 _) = (GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT) glFormat (ImageRGB8 _) = (GL_RGB, GL_UNSIGNED_BYTE) glFormat (ImageRGB16 _) = (GL_RGB, GL_UNSIGNED_SHORT) glFormat (ImageRGBF _) = (GL_RGB, GL_FLOAT) glFormat (ImageRGBA8 _) = (GL_RGBA, GL_UNSIGNED_BYTE) glFormat (ImageRGBA16 _) = (GL_RGBA, GL_UNSIGNED_BYTE) glFormat (ImageYCbCr8 _) = (GL_YCRCB_444_SGIX, GL_UNSIGNED_BYTE) glFormat (ImageCMYK8 _) = (GL_CMYK_EXT, GL_UNSIGNED_BYTE) glFormat (ImageCMYK16 _) = (GL_CMYK_EXT, GL_UNSIGNED_SHORT)