packages feed

gloss-raster-massiv (empty) → 0.1.0.0

raw patch · 6 files changed

+596/−0 lines, 6 filesdep +basedep +derive-storabledep +derive-storable-plugin

Dependencies added: base, derive-storable, derive-storable-plugin, generic-deriving, gloss, gloss-raster-massiv, gloss-rendering, massiv

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for gloss-raster-massiv++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2023, Matthew Mosior++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Matthew Mosior nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ gloss-raster-massiv.cabal view
@@ -0,0 +1,111 @@+cabal-version:      3.0+-- The cabal-version field refers to the version of the .cabal specification,+-- and can be different from the cabal-install (the tool) version and the+-- Cabal (the library) version you are using. As such, the Cabal (the library)+-- version used must be equal or greater than the version stated in this field.+-- Starting from the specification version 2.2, the cabal-version field must be+-- the first thing in the cabal file.++-- Initial package description 'gloss-raster-massiv' generated by+-- 'cabal init'. For further documentation, see:+--   http://haskell.org/cabal/users-guide/+--+-- The name of the package.+name:               gloss-raster-massiv++-- The package version.+-- See the Haskell package versioning policy (PVP) for standards+-- guiding when and how versions should be incremented.+-- https://pvp.haskell.org+-- PVP summary:     +-+------- breaking API changes+--                  | | +----- non-breaking API additions+--                  | | | +--- code changes with no API change+version:            0.1.0.0++-- A short (one-line) description of the package.+synopsis: Massiv-based alternative for gloss-raster++-- A longer description of the package.+description: This library utilizes massiv's superb performance characteristics to supply alternative rasterization functionality to that which is provided by the gloss-raster package.++-- The license under which the package is released.+license:            BSD-3-Clause++-- The file containing the license text.+license-file:       LICENSE++-- The package author(s).+author:             Matthew Mosior++-- An email address to which users can send suggestions, bug reports, and patches.+maintainer:         mattm.github@gmail.com++-- A copyright notice.+-- copyright:+category:           Graphics+build-type:         Simple++-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README.+extra-doc-files:    CHANGELOG.md++-- Extra source files to be distributed with the package, such as examples, or a tutorial module.+-- extra-source-files:++common warnings+    ghc-options: -Wall++library+    -- Import common warning flags.+    import:           warnings++    -- Modules exported by the library.+    exposed-modules:  Graphics.Gloss.Raster.Array,+                      Graphics.Gloss.Raster.Massiv.Internal++    -- Modules included in this library but not exported.+    -- other-modules:++    -- LANGUAGE extensions used by modules in this package.+    -- other-extensions:++    -- Other library packages from which modules are imported.+    build-depends:    base ^>=4.17.1.0,+                      derive-storable >= 0.3.1 && < 0.4,+                      derive-storable-plugin >= 0.2.3 && < 0.3,+                      generic-deriving >= 1.14.4 && < 1.15,+                      gloss >= 1.13.2 && < 1.14,+                      gloss-rendering >= 1.13.1 && < 1.14,+                      massiv >= 1.0.4 && < 1.1++    -- Directories containing source files.+    hs-source-dirs:   src++    -- Base language which the package is written in.+    default-language: Haskell2010++test-suite gloss-raster-massiv-test+    -- Import common warning flags.+    import:           warnings++    -- Base language which the package is written in.+    default-language: Haskell2010++    -- Modules included in this executable, other than Main.+    -- other-modules:++    -- LANGUAGE extensions used by modules in this package.+    -- other-extensions:++    -- The interface type and version of the test suite.+    type:             exitcode-stdio-1.0++    -- Directories containing source files.+    hs-source-dirs:   test++    -- The entrypoint to the test suite.+    main-is:          Main.hs++    -- Test dependencies.+    build-depends:+        base ^>=4.17.1.0,+        gloss-raster-massiv
+ src/Graphics/Gloss/Raster/Array.hs view
@@ -0,0 +1,234 @@+{-# LANGUAGE BangPatterns                                #-}+{-# LANGUAGE DeriveDataTypeable                          #-}+{-# LANGUAGE DeriveGeneric                               #-}+{-# LANGUAGE FlexibleContexts                            #-}+{-# LANGUAGE MagicHash                                   #-}+{-# LANGUAGE MultiWayIf                                  #-}+{-# LANGUAGE PatternGuards                               #-}+{-# LANGUAGE ScopedTypeVariables                         #-}+{-# LANGUAGE TypeApplications                            #-}+{-# OPTIONS_GHC -fplugin=Foreign.Storable.Generic.Plugin #-}++-- |+-- Module      :  Graphics.Gloss.Raster.Array+-- Copyright   :  (c) Matthew Mosior 2023+-- License     :  BSD-style+-- Maintainer  :  mattm.github@gmail.com+-- Portability :  portable+--+-- = Massiv-based alternative for gloss-raster+--+-- This library utilizes [massiv](https://hackage.haskell.org/package/massiv-1.0.4.0)'s superb performance characteristics to supply alternative rasterization functionality to that which is provided by the [gloss-raster](https://hackage.haskell.org/package/gloss-raster) package.++module Graphics.Gloss.Raster.Array ( -- * Graphics.Gloss.Raster.Array Replacement functions - Display functions+                                     animateArrayMassiv,+                                     playArrayMassiv,+                                     animateArrayMassivIO,+                                     playArrayMassivIO,+                                     sizeOfDisplay +                                   ) where++import Graphics.Gloss.Raster.Massiv.Internal++import Data.Bits+import Data.Word+import Data.Massiv.Array as DMA+import Data.Massiv.Array.Unsafe as DMAU+import Debug.Trace+import Graphics.Gloss.Data.Picture+import Graphics.Gloss.Data.Display+import Graphics.Gloss.Data.Bitmap+import Graphics.Gloss.Interface.Pure.Game+import Graphics.Gloss.Interface.IO.Animate+import Graphics.Gloss.Interface.IO.Game+import Graphics.Gloss.Interface.Environment+import System.IO.Unsafe+import Unsafe.Coerce++-- | A more performant replacement of+-- [animateArray](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html#v:animateArray)+-- found in [Graphics.Gloss.Raster.Array](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html).+--+-- Animate a bitmap generated from a Massiv array.+animateArrayMassiv :: Display                                -- ^ Display mode.+                   -> (Int,Int)                              -- ^ Number of pixels to draw per element.+                   -> (Float -> Array DMA.S Ix2 ColorMassiv) -- ^ A function to construct a delayed array for the given time.+                                                             --   The function should return an array of the same extent each+                                                             --   time it is applied.+                                                             --+                                                             --   It is passed the time in seconds since the program started.+                   -> IO ()+animateArrayMassiv display scalemassiv@(scaleX, scaleY) makeMassivArray =+  scaleX `seq` scaleY `seq`+  if | scaleX < 1 || scaleY < 1+     -> error $ "Graphics.Gloss.Raster.Massiv.Array: invalid pixel scale factor "+                ++ show (scaleX,scaleY)+     | otherwise+     -> let {-# INLINE frame #-}+            frame !time          = return $ makeFrame scalemassiv (makeMassivArray time)+        in  animateFixedIO display black frame (const $ return ())+{-# INLINE animateArrayMassiv #-}++-- | A more performant replacement of+-- [animateArrayIO](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html#v:animateArrayIO)+-- found in [Graphics.Gloss.Raster.Array](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html).+--+-- Animate a bitmap generated from a Massiv array, via the IO monad.+animateArrayMassivIO :: Display                                     -- ^ Display mode.+                     -> (Int,Int)                                   -- ^ Number of pixels to draw per element.+                     -> (Float -> IO (Array DMA.S Ix2 ColorMassiv)) -- ^ A function to construct a delayed array for the given time.+                                                                    --   The function should return an array of the same extent each+                                                                    --   time it is applied.+                                                                    --+                                                                    --   It is passed the time in seconds since the program started.+                     -> IO ()+animateArrayMassivIO display scalemassiv@(scaleX, scaleY) makeMassivArray =+  scaleX `seq` scaleY `seq`+  if | scaleX < 1 || scaleY < 1+     -> error $ "Graphics.Gloss.Raster.Massiv.Array: invalid pixel scale factor "+                ++ show (scaleX,scaleY)+     | otherwise+     -> let {-# INLINE frame #-}+            frame !time          = fmap (makeFrame scalemassiv) (makeMassivArray time)+        in  animateFixedIO display black frame (const $ return ())+{-# INLINE animateArrayMassivIO #-}++-- | A more performant replacement of+-- [playArray](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html#v:playArray)+-- found in [Graphics.Gloss.Raster.Array](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html).+--+-- Play with a bitmap generated from a Massiv array.+playArrayMassiv :: Display                                -- ^ Display mode.+                -> (Int,Int)                              -- ^ Number of pixels to draw per element.+                -> Int                                    -- ^ Number of simulation steps to take+                                                          --   for each second of real time+                -> world                                  -- ^ The initial world.+                -> (world -> Array DMA.S Ix2 ColorMassiv) -- ^ Function to convert the world to an array.+                -> (Event -> world -> world)              -- ^ Function to handle input events.+                -> (Float -> world -> world)              -- ^ Function to step the world one iteration.+                                                          --   It is passed the time in seconds since the program started.+                -> IO ()+playArrayMassiv !display scalemassiv@(scaleX, scaleY) !stepRate+                !initWorld !makeMassivArray !handleEvent !stepWorld =+  scaleX `seq` scaleY `seq`+  if | scaleX < 1 || scaleY < 1+     -> error $ "Graphics.Gloss.Raster.Massiv.Array: invalid pixel scale factor "+                ++ show scalemassiv+     | otherwise+     -> let  {-# INLINE frame #-}+             frame !world    = makeFrame scalemassiv (makeMassivArray world)+        in   play display black+                     stepRate+                     initWorld+                     frame+                     handleEvent+                     stepWorld+{-# INLINE playArrayMassiv #-}++-- | A more performant replacement of+-- [playArrayIO](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html#v:playArrayIO)+-- found in [Graphics.Gloss.Raster.Array](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html).+--+-- Play with a bitmap generated from a Massiv array, via the IO monad.+playArrayMassivIO :: Display                                     -- ^ Display mode.+                  -> (Int,Int)                                   -- ^ Number of pixels to draw per element.+                  -> Int                                         -- ^ Number of simulation steps to take+                                                                 --   for each second of real time+                  -> world                                       -- ^ The initial world.+                  -> (world -> IO (Array DMA.S Ix2 ColorMassiv)) -- ^ Function to convert the world to an array.+                  -> (Event -> world -> IO world)                -- ^ Function to handle input events.+                  -> (Float -> world -> IO world)                -- ^ Function to step the world one iteration.+                                                                 --   It is passed the time in seconds since the program started.+                  -> IO ()+playArrayMassivIO !display scalemassiv@(scaleX, scaleY) !stepRate+                  !initWorld !makeMassivArray !handleEvent !stepWorld =+  scaleX `seq` scaleY `seq`+  if | scaleX < 1 || scaleY < 1+     -> error $ "Graphics.Gloss.Raster.Array: invalid pixel scale factor "+                ++ show scalemassiv+     | otherwise+     -> let  {-# INLINE frame #-}+             frame !world    = fmap (makeFrame scalemassiv) (makeMassivArray world)+        in  playIO display black+                     stepRate+                     initWorld+                     frame+                     handleEvent+                     stepWorld+{-# INLINE playArrayMassivIO #-}++-- | A more performant replacement of+-- [makeFrame](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html)+-- found in [Graphics.Gloss.Raster.Array](https://hackage.haskell.org/package/gloss-raster-1.13.1.2/docs/Graphics-Gloss-Raster-Array.html).+makeFrame :: (Int,Int)+          -> Array DMA.S Ix2 ColorMassiv+          -> Picture+makeFrame (scaleX,scaleY) !array+ = let  -- Size of the array+        (Sz2 sizeY sizeX) = DMA.size array++        convColor :: ColorMassiv+                  -> Word32+        convColor colormassiv+         = let  (r,g,b) = unpackColorMassiv colormassiv+                r'      = fromIntegral r+                g'      = fromIntegral g+                b'      = fromIntegral b+                a       = 255+                !w      =  unsafeShiftL r' 24+                       .|. unsafeShiftL g' 16+                       .|. unsafeShiftL b' 8+                       .|. a+           in w+        {-# INLINE convColor #-}++   in unsafePerformIO $ do++        -- Define the image, and extract out just the RGB color components.+        -- We don't need the alpha because we're only drawing one image.+        traceEventIO "Gloss.Raster.Massiv[makeFrame]: start frame evaluation."+        let arrRGB = DMA.map convColor array :: Array DMA.D Ix2 Word32+        traceEventIO "Gloss.Raster.Massiv[makeFrame]: done, returning picture."++        -- Wrap the ForeignPtr from the Array as a gloss picture.+        let picture+                = Scale (fromIntegral scaleX) (fromIntegral scaleY)+                $ bitmapOfForeignPtr+                        sizeX sizeY     -- raw image size+                        (BitmapFormat BottomToTop PxABGR)+                        ((\(a,_) -> a) $ DMAU.unsafeArrayToForeignPtr $ (unsafeCoerce arrRGB :: Array DMA.S Ix2 Word8)) +                                        -- the image data.+                        False           -- don't cache this in texture memory.++        return picture+{-# INLINE makeFrame #-}++-- | Float to Word8 conversion because the one in the GHC libraries+-- doesn't have enout specialisations and goes via Integer.+word8OfFloat :: Float+             -> Word8+word8OfFloat f+        = fromIntegral (truncate f :: Int)+{-# INLINE word8OfFloat #-}++-- | Function to unpack a ColorMassiv+-- into a triplet of Word8's.+unpackColorMassiv :: ColorMassiv+                  -> (Word8,Word8,Word8)+unpackColorMassiv c+        | (r,g,b,_) <- rgbaOfColorMassiv c+        = ( word8OfFloat (r * 255)+          , word8OfFloat (g * 255)+          , word8OfFloat (b * 255)+          )+{-# INLINE unpackColorMassiv #-}++-- | Function that takes a display+-- and returns a tuple of the x and y scale.+sizeOfDisplay :: Display+              -> IO (Int,Int)+sizeOfDisplay display+ = case display of+        InWindow _ s _  -> return s+        FullScreen      -> getScreenSize+{-# INLINE sizeOfDisplay #-}
+ src/Graphics/Gloss/Raster/Massiv/Internal.hs view
@@ -0,0 +1,212 @@+{-# LANGUAGE BangPatterns                                #-}+{-# LANGUAGE DeriveDataTypeable                          #-}+{-# LANGUAGE DeriveGeneric                               #-}+{-# LANGUAGE FlexibleContexts                            #-}+{-# LANGUAGE MagicHash                                   #-}+{-# LANGUAGE MultiWayIf                                  #-}+{-# LANGUAGE PatternGuards                               #-}+{-# LANGUAGE ScopedTypeVariables                         #-}+{-# LANGUAGE TypeApplications                            #-}+{-# OPTIONS_GHC -fplugin=Foreign.Storable.Generic.Plugin #-}++-- |+-- Module      :  Graphics.Gloss.Raster.Massiv.Internal+-- Copyright   :  (c) Matthew Mosior 2023+-- License     :  BSD-style+-- Maintainer  :  mattm.github@gmail.com+-- Portability :  portable+--+-- = WARNING+--+-- This module is considered __internal__.+--+-- The Package Versioning Policy __does not apply__.+--+-- The contents of this module may change __in any way whatsoever__+-- and __without any warning__ between minor versions of this package.+--+-- Authors importing this library are expected to track development+-- closely.+--+-- All credit goes to the author(s)/maintainer(s) of the+-- [containers](https://hackage.haskell.org/package/containers) library+-- for the above warning text.+--+-- = Description+--+-- This library utilizes [massiv](https://hackage.haskell.org/package/massiv-1.0.4.0)'s superb performance characteristics to supply alternative rasterization functionality to that which is provided by the [gloss-raster](https://hackage.haskell.org/package/gloss-raster) package.++module Graphics.Gloss.Raster.Massiv.Internal ( -- * Graphics.Gloss.Raster.Array Replacement functions - INTERNAL+                                               ColorMassiv(..),+                                               rgbMassiv,+                                               rgbMassivI,+                                               rgbMassiv8w,+                                               rgbMassiv',+                                               rgbMassivI',+                                               makeColorMassiv,+                                               makeColorMassivI,+                                               makeRawColorMassiv,+                                               makeRawColorMassivI,+                                               rgbaOfColorMassiv+                                             ) where++import Data.Data+import Data.Word+import Foreign.Storable.Generic+import Generics.Deriving.Base++-- | Custom [Color](https://hackage.haskell.org/package/gloss-rendering-1.13.1.1/docs/Graphics-Gloss-Rendering.html#t:Color) data type.+data ColorMassiv = RGBA !Float !Float !Float !Float+  deriving (Show,Eq,Data,Generic,Typeable)++instance Num ColorMassiv where+ (+) (RGBA r1 g1 b1 _) (RGBA r2 g2 b2 _)+        = RGBA (r1 + r2) (g1 + g2) (b1 + b2) 1+ {-# INLINE (+) #-}++ (-) (RGBA r1 g1 b1 _) (RGBA r2 g2 b2 _)+        = RGBA (r1 - r2) (g1 - g2) (b1 - b2) 1+ {-# INLINE (-) #-}++ (*) (RGBA r1 g1 b1 _) (RGBA r2 g2 b2 _)+        = RGBA (r1 * r2) (g1 * g2) (b1 * b2) 1+ {-# INLINE (*) #-}++ abs (RGBA r1 g1 b1 _)+        = RGBA (abs r1) (abs g1) (abs b1) 1+ {-# INLINE abs #-}++ signum (RGBA r1 g1 b1 _)+        = RGBA (signum r1) (signum g1) (signum b1) 1+ {-# INLINE signum #-}++ fromInteger i+  = let f = fromInteger i+    in  RGBA f f f 1+ {-# INLINE fromInteger #-}++instance GStorable ColorMassiv++-- | Make a custom color. All components are clamped to the range  [0..1].+makeColorMassiv :: Float        -- ^ Red component.+                -> Float        -- ^ Green component.+                -> Float        -- ^ Blue component.+                -> Float        -- ^ Alpha component.+                -> ColorMassiv+makeColorMassiv r g b a+        = clampColorMassiv+        $ RGBA r g b a+{-# INLINE makeColorMassiv #-}++-- | Make a custom color. All components are clamped to the range [0..255].+makeColorMassivI :: Int+                 -> Int+                 -> Int+                 -> Int+                 -> ColorMassiv+makeColorMassivI r g b a+        = clampColorMassiv+        $ RGBA  (fromIntegral r / 255)+                (fromIntegral g / 255)+                (fromIntegral b / 255)+                (fromIntegral a / 255)+{-# INLINE makeColorMassivI #-}++-- | Make a custom color.+--+--   Using this function over `makeColor` avoids clamping the components,+--   which saves time. However, if the components are out of range then+--   this will result in integer overflow at rendering time, and the actual+--   picture you get will be implementation dependent.+--+--   You'll only need to use this function when using the @gloss-raster@+--   package that builds a new color for every pixel. If you're just working+--   with the Picture data type then it there is no need for raw colors.+makeRawColorMassiv :: Float+                   -> Float+                   -> Float+                   -> Float+                   -> ColorMassiv+makeRawColorMassiv r g b a+        = RGBA r g b a+{-# INLINE makeRawColorMassiv #-}++-- | Make a custom color, taking pre-clamped components.+makeRawColorMassivI :: Int+                    -> Int+                    -> Int+                    -> Int+                    -> ColorMassiv+makeRawColorMassivI r g b a+        = RGBA  (fromIntegral r / 255)+                (fromIntegral g / 255)+                (fromIntegral b / 255)+                (fromIntegral a / 255)+{-# INLINE makeRawColorMassivI #-}++-- | Take the RGBA components of a color.+rgbaOfColorMassiv :: ColorMassiv+                  -> (Float,Float,Float,Float)+rgbaOfColorMassiv (RGBA r g b a) = (r,g,b,a)+{-# INLINE rgbaOfColorMassiv #-}+++-- | Clamp components of a raw color into the required range.+clampColorMassiv :: ColorMassiv+                 -> ColorMassiv+clampColorMassiv cc+ = let  (r,g,b,a)    = rgbaOfColorMassiv cc+        clamp x      = (min (max x 0.0) 1.0)+   in   RGBA (clamp r) (clamp g) (clamp b) (clamp a)++-- | Construct a color from red, green, blue components.+--+--   Each component is clamped to the range [0..1]+rgbMassiv :: Float+          -> Float+          -> Float+          -> ColorMassiv+rgbMassiv r g b = makeColorMassiv r g b 1.0+{-# INLINE rgbMassiv #-}++-- | Construct a color from red, green, blue components.+--+--   Each component is clamped to the range [0..255]+rgbMassivI :: Int+           -> Int+           -> Int+           -> ColorMassiv+rgbMassivI r g b = makeColorMassivI r g b 255+{-# INLINE rgbMassivI #-}++-- | Construct a color from red, green, blue components.+rgbMassiv8w :: Word8+            -> Word8+            -> Word8+            -> ColorMassiv+rgbMassiv8w r g b = makeRawColorMassivI (fromIntegral r) (fromIntegral g) (fromIntegral b) 255+{-# INLINE rgbMassiv8w #-}++-- | Like `rgb`, but take pre-clamped components for speed.+--+--   If you're building a new color for every pixel then use this version,+--   however if your components are out of range then the picture you get will+--   be implementation dependent.+rgbMassiv' :: Float+           -> Float+           -> Float+           -> ColorMassiv+rgbMassiv' r g b  = makeRawColorMassiv r g b 1.0+{-# INLINE rgbMassiv' #-}++-- | Like `rgbI`, but take pre-clamped components for speed.+--+--   If you're building a new color for every pixel then use this version,+--   however if your components are out of range then the picture you get will+--   be implementation dependent.+rgbMassivI' :: Int+            -> Int+            -> Int+            -> ColorMassiv+rgbMassivI' r g b = makeRawColorMassivI r g b 255+{-# INLINE rgbMassivI' #-}
+ test/Main.hs view
@@ -0,0 +1,4 @@+module Main (main) where++main :: IO ()+main = putStrLn "Test suite not yet implemented."