@@ 0,0 1,65 @@
+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)