packages feed

hip 1.3.0.0 → 1.4.0.0

raw patch · 49 files changed

+4939/−2358 lines, 49 filesdep ~repadep ~vectorPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: repa, vector

API changes (from Hackage documentation)

- Graphics.Image: RP :: RP
- Graphics.Image: RS :: RS
- Graphics.Image: VU :: VU
- Graphics.Image: data RP
- Graphics.Image: data RS
- Graphics.Image: data VU
- Graphics.Image: fromListsP :: Array RP cs e => [[Pixel cs e]] -> Image RP cs e
- Graphics.Image: fromListsS :: Array RS cs e => [[Pixel cs e]] -> Image RS cs e
- Graphics.Image: makeImageP :: Array RP cs Double => (Int, Int) -> ((Int, Int) -> Pixel cs Double) -> Image RP cs Double
- Graphics.Image: makeImageS :: Array RS cs Double => (Int, Int) -> ((Int, Int) -> Pixel cs Double) -> Image RS cs Double
- Graphics.Image.ColorSpace: Y :: Y
- Graphics.Image.ColorSpace: YA :: YA
- Graphics.Image.ColorSpace: class (ColorSpace (Opaque cs), ColorSpace cs) => Alpha cs where type Opaque cs where {
- Graphics.Image.ColorSpace: data family Pixel cs e;
- Graphics.Image.Interface: chApp :: ColorSpace cs => Pixel cs (e' -> e) -> Pixel cs e' -> Pixel cs e
- Graphics.Image.Interface: chOp :: ColorSpace cs => (cs -> e' -> e) -> Pixel cs e' -> Pixel cs e
- Graphics.Image.Interface: class (ColorSpace (Opaque cs), ColorSpace cs) => Alpha cs where type Opaque cs where {
- Graphics.Image.Interface: csColour :: ColorSpace cs => cs -> AlphaColour Double
- Graphics.Image.Interface: fromChannel :: ColorSpace cs => e -> Pixel cs e
- Graphics.Image.Interface: fromElt :: ColorSpace cs => PixelElt cs e -> Pixel cs e
- Graphics.Image.Interface: getPxCh :: ColorSpace cs => Pixel cs e -> cs -> e
- Graphics.Image.Interface: instance (Graphics.Image.Interface.ColorSpace cs, GHC.Enum.Bounded e) => GHC.Enum.Bounded (Graphics.Image.Interface.Pixel cs e)
- Graphics.Image.Interface: instance (Graphics.Image.Interface.ColorSpace cs, GHC.Float.Floating e) => GHC.Float.Floating (Graphics.Image.Interface.Pixel cs e)
- Graphics.Image.Interface: instance (Graphics.Image.Interface.ColorSpace cs, GHC.Num.Num e) => GHC.Num.Num (Graphics.Image.Interface.Pixel cs e)
- Graphics.Image.Interface: instance (Graphics.Image.Interface.ColorSpace cs, GHC.Real.Fractional e) => GHC.Real.Fractional (Graphics.Image.Interface.Pixel cs e)
- Graphics.Image.Interface: instance Graphics.Image.Interface.ColorSpace cs => Data.Foldable.Foldable (Graphics.Image.Interface.Pixel cs)
- Graphics.Image.Interface: instance Graphics.Image.Interface.ColorSpace cs => GHC.Base.Applicative (Graphics.Image.Interface.Pixel cs)
- Graphics.Image.Interface: instance Graphics.Image.Interface.ColorSpace cs => GHC.Base.Functor (Graphics.Image.Interface.Pixel cs)
- Graphics.Image.Interface: opaque :: Alpha cs => cs -> Opaque cs
- Graphics.Image.Interface: pxFoldMap :: (ColorSpace cs, Monoid m) => (e -> m) -> Pixel cs e -> m
- Graphics.Image.Interface: pxOp :: ColorSpace cs => (e' -> e) -> Pixel cs e' -> Pixel cs e
- Graphics.Image.Interface: toElt :: ColorSpace cs => Pixel cs e -> PixelElt cs e
- Graphics.Image.Interface: type Elt arr cs e = ();
- Graphics.Image.Interface.Repa: RP :: RP
- Graphics.Image.Interface.Repa: RS :: RS
- Graphics.Image.Interface.Repa: data RP
- Graphics.Image.Interface.Repa: data RS
- Graphics.Image.Interface.Repa: fromListsP :: Array RP cs e => [[Pixel cs e]] -> Image RP cs e
- Graphics.Image.Interface.Repa: fromListsS :: Array RS cs e => [[Pixel cs e]] -> Image RS cs e
- Graphics.Image.Interface.Repa: fromRepaArrayP :: Array D DIM2 (Pixel cs e) -> Image RP cs e
- Graphics.Image.Interface.Repa: fromRepaArrayS :: Array D DIM2 (Pixel cs e) -> Image RS cs e
- Graphics.Image.Interface.Repa: makeImageP :: Array RP cs Double => (Int, Int) -> ((Int, Int) -> Pixel cs Double) -> Image RP cs Double
- Graphics.Image.Interface.Repa: makeImageS :: Array RS cs Double => (Int, Int) -> ((Int, Int) -> Pixel cs Double) -> Image RS cs Double
- Graphics.Image.Interface.Vector: fromLists :: Array VU cs e => [[Pixel cs e]] -> Image VU cs e
- Graphics.Image.Interface.Vector: makeImage :: Array VU cs Double => (Int, Int) -> ((Int, Int) -> Pixel cs Double) -> Image VU cs Double
- Graphics.Image.Processing.Complex: cis' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs e -> Image arr cs (Complex e)
- Graphics.Image.Processing.Complex: conjugate' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs (Complex e)
- Graphics.Image.Processing.Complex: imagPart' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs e
- Graphics.Image.Processing.Complex: magnitude' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs e
- Graphics.Image.Processing.Complex: mkPolar' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs e -> Image arr cs e -> Image arr cs (Complex e)
- Graphics.Image.Processing.Complex: phase' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs e
- Graphics.Image.Processing.Complex: polar' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> (Image arr cs e, Image arr cs e)
- Graphics.Image.Processing.Complex: realPart' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs e
- Graphics.Image.Types: RP :: RP
- Graphics.Image.Types: RS :: RS
- Graphics.Image.Types: data RP
- Graphics.Image.Types: data RS
+ Graphics.Image: fromListsR :: Array arr cs e => arr -> [[Pixel cs e]] -> Image arr cs e
+ Graphics.Image: makeImageR :: Array arr cs Double => arr -> (Int, Int) -> ((Int, Int) -> Pixel cs Double) -> Image arr cs Double
+ Graphics.Image.ColorSpace: LumaY :: Y
+ Graphics.Image.ColorSpace: LumaYA :: YA
+ Graphics.Image.ColorSpace: addAlpha :: AlphaSpace cs e => e -> Pixel (Opaque cs) e -> Pixel cs e
+ Graphics.Image.ColorSpace: class (ColorSpace (Opaque cs) e, ColorSpace cs e) => AlphaSpace cs e where type Opaque cs where {
+ Graphics.Image.ColorSpace: dropAlpha :: AlphaSpace cs e => Pixel cs e -> Pixel (Opaque cs) e
+ Graphics.Image.ColorSpace: getAlpha :: AlphaSpace cs e => Pixel cs e -> e
+ Graphics.Image.ColorSpace: instance Graphics.Image.Interface.Elevator GHC.Int.Int16
+ Graphics.Image.ColorSpace: instance Graphics.Image.Interface.Elevator GHC.Int.Int32
+ Graphics.Image.ColorSpace: instance Graphics.Image.Interface.Elevator GHC.Int.Int64
+ Graphics.Image.ColorSpace: instance Graphics.Image.Interface.Elevator GHC.Int.Int8
+ Graphics.Image.ColorSpace: instance Graphics.Image.Interface.Elevator GHC.Types.Int
+ Graphics.Image.ColorSpace: instance Graphics.Image.Interface.Elevator GHC.Types.Word
+ Graphics.Image.IO.Histogram: class ChannelColour cs
+ Graphics.Image.IO.Histogram: csColour :: ChannelColour cs => cs -> AlphaColour Double
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.CMYK.CMYK
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.CMYK.CMYKA
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.Gray.Gray
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.HSI.HSI
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.HSI.HSIA
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.Luma.Y
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.Luma.YA
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.RGB.RGB
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.RGB.RGBA
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.YCbCr.YCbCr
+ Graphics.Image.IO.Histogram: instance Graphics.Image.IO.Histogram.ChannelColour Graphics.Image.ColorSpace.YCbCr.YCbCrA
+ Graphics.Image.Interface: broadcastC :: ColorSpace cs e => e -> Pixel cs e
+ Graphics.Image.Interface: checkDims :: String -> (Int, Int) -> (Int, Int)
+ Graphics.Image.Interface: class (ColorSpace (Opaque cs) e, ColorSpace cs e) => AlphaSpace cs e where type Opaque cs where {
+ Graphics.Image.Interface: foldIx :: Array arr cs e => (Pixel cs e -> (Int, Int) -> Pixel cs e -> Pixel cs e) -> Pixel cs e -> Image arr cs e -> Pixel cs e
+ Graphics.Image.Interface: foldl1Px :: ColorSpace cs e => (e -> e -> e) -> Pixel cs e -> e
+ Graphics.Image.Interface: foldlPx :: ColorSpace cs e => (b -> e -> b) -> b -> Pixel cs e -> b
+ Graphics.Image.Interface: foldrPx :: ColorSpace cs e => (e -> b -> b) -> b -> Pixel cs e -> b
+ Graphics.Image.Interface: fromComponents :: ColorSpace cs e => Components cs e -> Pixel cs e
+ Graphics.Image.Interface: fromIx :: Int -> (Int, Int) -> Int
+ Graphics.Image.Interface: getPxC :: ColorSpace cs e => Pixel cs e -> cs -> e
+ Graphics.Image.Interface: instance (Data.Foldable.Foldable (Graphics.Image.Interface.Pixel cs), Control.DeepSeq.NFData e) => Control.DeepSeq.NFData (Graphics.Image.Interface.Pixel cs e)
+ Graphics.Image.Interface: instance (GHC.Base.Applicative (Graphics.Image.Interface.Pixel cs), GHC.Enum.Bounded e) => GHC.Enum.Bounded (Graphics.Image.Interface.Pixel cs e)
+ Graphics.Image.Interface: makeImageWindowed :: Array arr cs e => (Int, Int) -> ((Int, Int), (Int, Int)) -> ((Int, Int) -> Pixel cs e) -> ((Int, Int) -> Pixel cs e) -> Image arr cs e
+ Graphics.Image.Interface: mapPx :: ColorSpace cs e => (e -> e) -> Pixel cs e -> Pixel cs e
+ Graphics.Image.Interface: mapPxC :: ColorSpace cs e => (cs -> e -> e) -> Pixel cs e -> Pixel cs e
+ Graphics.Image.Interface: setPxC :: ColorSpace cs e => Pixel cs e -> cs -> e -> Pixel cs e
+ Graphics.Image.Interface: toComponents :: ColorSpace cs e => Pixel cs e -> Components cs e
+ Graphics.Image.Interface: toIx :: Int -> Int -> (Int, Int)
+ Graphics.Image.Interface: toListPx :: ColorSpace cs e => Pixel cs e -> [e]
+ Graphics.Image.Interface: type SuperClass arr cs e = ();
+ Graphics.Image.Interface: zipWithPx :: ColorSpace cs e => (e -> e -> e) -> Pixel cs e -> Pixel cs e -> Pixel cs e
+ Graphics.Image.Interface.Repa: RPS :: RPS
+ Graphics.Image.Interface.Repa: RPU :: RPU
+ Graphics.Image.Interface.Repa: RSS :: RSS
+ Graphics.Image.Interface.Repa: RSU :: RSU
+ Graphics.Image.Interface.Repa: data RPS
+ Graphics.Image.Interface.Repa: data RPU
+ Graphics.Image.Interface.Repa: data RSS
+ Graphics.Image.Interface.Repa: data RSU
+ Graphics.Image.Interface.Repa: instance Graphics.Image.Interface.Exchangable Graphics.Image.Interface.Repa.Storable.RPS Graphics.Image.Interface.Repa.Unboxed.RPU
+ Graphics.Image.Interface.Repa: instance Graphics.Image.Interface.Exchangable Graphics.Image.Interface.Repa.Storable.RSS Graphics.Image.Interface.Repa.Unboxed.RSU
+ Graphics.Image.Interface.Repa: instance Graphics.Image.Interface.Exchangable Graphics.Image.Interface.Repa.Unboxed.RPU Graphics.Image.Interface.Repa.Storable.RPS
+ Graphics.Image.Interface.Repa: instance Graphics.Image.Interface.Exchangable Graphics.Image.Interface.Repa.Unboxed.RSU Graphics.Image.Interface.Repa.Storable.RSS
+ Graphics.Image.Interface.Vector: VS :: VS
+ Graphics.Image.Interface.Vector: data VS
+ Graphics.Image.Interface.Vector: fromStorableVector :: Array VS cs e => (Int, Int) -> Vector (Pixel cs e) -> Image VS cs e
+ Graphics.Image.Interface.Vector: instance Graphics.Image.Interface.Exchangable Graphics.Image.Interface.Vector.Storable.VS Graphics.Image.Interface.Vector.Unboxed.VU
+ Graphics.Image.Interface.Vector: instance Graphics.Image.Interface.Exchangable Graphics.Image.Interface.Vector.Unboxed.VU Graphics.Image.Interface.Vector.Storable.VS
+ Graphics.Image.Interface.Vector: toStorableVector :: Array VS cs e => Image VS cs e -> Vector (Pixel cs e)
+ Graphics.Image.Processing.Complex: cisI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs e -> Image arr cs (Complex e)
+ Graphics.Image.Processing.Complex: conjugateI :: (Applicative (Pixel cs), Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs (Complex e)
+ Graphics.Image.Processing.Complex: imagPartI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs e
+ Graphics.Image.Processing.Complex: magnitudeI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs e
+ Graphics.Image.Processing.Complex: mkPolarI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs e -> Image arr cs e -> Image arr cs (Complex e)
+ Graphics.Image.Processing.Complex: phaseI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs e
+ Graphics.Image.Processing.Complex: polarI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> (Image arr cs e, Image arr cs e)
+ Graphics.Image.Processing.Complex: realPartI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs e
+ Graphics.Image.Types: RPS :: RPS
+ Graphics.Image.Types: RPU :: RPU
+ Graphics.Image.Types: RSS :: RSS
+ Graphics.Image.Types: RSU :: RSU
+ Graphics.Image.Types: VS :: VS
+ Graphics.Image.Types: data RPS
+ Graphics.Image.Types: data RPU
+ Graphics.Image.Types: data RSS
+ Graphics.Image.Types: data RSU
+ Graphics.Image.Types: data VS
- Graphics.Image: fromLists :: Array VU cs e => [[Pixel cs e]] -> Image VU cs e
+ Graphics.Image: fromLists :: Array arr cs e => [[Pixel cs e]] -> Image arr cs e
- Graphics.Image: makeImage :: Array VU cs Double => (Int, Int) -> ((Int, Int) -> Pixel cs Double) -> Image VU cs Double
+ Graphics.Image: makeImage :: Array arr cs e => (Int, Int) -> ((Int, Int) -> Pixel cs e) -> Image arr cs e
- Graphics.Image: normalize :: (Array arr cs e, Array arr Gray e, Fractional e, Ord e) => Image arr cs e -> Image arr cs e
+ Graphics.Image: normalize :: (Array arr cs e, Array arr Gray e, Fractional e, Fractional (Pixel cs e), Ord e) => Image arr cs e -> Image arr cs e
- Graphics.Image: readImageExact :: Readable img format => format -> FilePath -> IO (Either String img)
+ Graphics.Image: readImageExact :: Readable (Image arr cs e) format => format -> FilePath -> IO (Either String (Image arr cs e))
- Graphics.Image: writeImageExact :: Writable img format => format -> [SaveOption format] -> FilePath -> img -> IO ()
+ Graphics.Image: writeImageExact :: Writable (Image arr cs e) format => format -> [SaveOption format] -> FilePath -> (Image arr cs e) -> IO ()
- Graphics.Image.ColorSpace: (+:) :: ColorSpace cs => Pixel cs e -> Pixel cs e -> Pixel cs (Complex e)
+ Graphics.Image.ColorSpace: (+:) :: Applicative (Pixel cs) => Pixel cs e -> Pixel cs e -> Pixel cs (Complex e)
- Graphics.Image.ColorSpace: cis :: (ColorSpace cs, RealFloat e) => Pixel cs e -> Pixel cs (Complex e)
+ Graphics.Image.ColorSpace: cis :: (Applicative (Pixel cs), RealFloat e) => Pixel cs e -> Pixel cs (Complex e)
- Graphics.Image.ColorSpace: class (Eq cs, Enum cs, Show cs, Typeable cs) => ColorSpace cs where data Pixel cs e where {
+ Graphics.Image.ColorSpace: class (Eq cs, Enum cs, Show cs, Typeable cs, Elevator e, Typeable e) => ColorSpace cs e where foldrPx f !z0 !xs = foldlPx f' id xs z0 where f' k x !z = k $! f x z foldlPx f !z0 !xs = foldrPx f' id xs z0 where f' x k !z = k $! f z x foldl1Px f !xs = fromMaybe (error "foldl1: empty Pixel") (foldlPx mf Nothing xs) where mf m !y = Just (case m of { Nothing -> y Just x -> f x y }) toListPx !px = foldr' f [] (enumFrom (toEnum 0)) where f !cs !ls = getPxC px cs : ls
- Graphics.Image.ColorSpace: class ColorSpace cs => ToCMYK cs where toImageCMYK = map toPixelCMYK
+ Graphics.Image.ColorSpace: class ColorSpace cs Double => ToCMYK cs where toImageCMYK = map toPixelCMYK
- Graphics.Image.ColorSpace: class (ToCMYK (Opaque cs), Alpha cs) => ToCMYKA cs where toPixelCMYKA px = addAlpha (getAlpha px) (toPixelCMYK (dropAlpha px)) toImageCMYKA = map toPixelCMYKA
+ Graphics.Image.ColorSpace: class (ToCMYK (Opaque cs), AlphaSpace cs Double) => ToCMYKA cs where toPixelCMYKA px = addAlpha (getAlpha px) (toPixelCMYK (dropAlpha px)) toImageCMYKA = map toPixelCMYKA
- Graphics.Image.ColorSpace: class ColorSpace cs => ToHSI cs where toImageHSI = map toPixelHSI
+ Graphics.Image.ColorSpace: class ColorSpace cs Double => ToHSI cs where toImageHSI = map toPixelHSI
- Graphics.Image.ColorSpace: class (ToHSI (Opaque cs), Alpha cs) => ToHSIA cs where toPixelHSIA px = addAlpha (getAlpha px) (toPixelHSI (dropAlpha px)) toImageHSIA = map toPixelHSIA
+ Graphics.Image.ColorSpace: class (ToHSI (Opaque cs), AlphaSpace cs Double) => ToHSIA cs where toPixelHSIA px = addAlpha (getAlpha px) (toPixelHSI (dropAlpha px)) toImageHSIA = map toPixelHSIA
- Graphics.Image.ColorSpace: class ColorSpace cs => ToRGB cs where toImageRGB = map toPixelRGB
+ Graphics.Image.ColorSpace: class ColorSpace cs Double => ToRGB cs where toImageRGB = map toPixelRGB
- Graphics.Image.ColorSpace: class (ToRGB (Opaque cs), Alpha cs) => ToRGBA cs where toPixelRGBA px = addAlpha (getAlpha px) (toPixelRGB (dropAlpha px)) toImageRGBA = map toPixelRGBA
+ Graphics.Image.ColorSpace: class (ToRGB (Opaque cs), AlphaSpace cs Double) => ToRGBA cs where toPixelRGBA px = addAlpha (getAlpha px) (toPixelRGB (dropAlpha px)) toImageRGBA = map toPixelRGBA
- Graphics.Image.ColorSpace: class ColorSpace cs => ToY cs where toImageY = map toPixelY
+ Graphics.Image.ColorSpace: class ColorSpace cs Double => ToY cs where toImageY = map toPixelY
- Graphics.Image.ColorSpace: class (ToY (Opaque cs), Alpha cs) => ToYA cs where toPixelYA px = addAlpha (getAlpha px) (toPixelY (dropAlpha px)) toImageYA = map toPixelYA
+ Graphics.Image.ColorSpace: class (ToY (Opaque cs), AlphaSpace cs Double) => ToYA cs where toPixelYA px = addAlpha (getAlpha px) (toPixelY (dropAlpha px)) toImageYA = map toPixelYA
- Graphics.Image.ColorSpace: class ColorSpace cs => ToYCbCr cs where toImageYCbCr = map toPixelYCbCr
+ Graphics.Image.ColorSpace: class ColorSpace cs Double => ToYCbCr cs where toImageYCbCr = map toPixelYCbCr
- Graphics.Image.ColorSpace: class (ToYCbCr (Opaque cs), Alpha cs) => ToYCbCrA cs where toPixelYCbCrA px = addAlpha (getAlpha px) (toPixelYCbCr (dropAlpha px)) toImageYCbCrA = map toPixelYCbCrA
+ Graphics.Image.ColorSpace: class (ToYCbCr (Opaque cs), AlphaSpace cs Double) => ToYCbCrA cs where toPixelYCbCrA px = addAlpha (getAlpha px) (toPixelYCbCr (dropAlpha px)) toImageYCbCrA = map toPixelYCbCrA
- Graphics.Image.ColorSpace: conjugate :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs (Complex e)
+ Graphics.Image.ColorSpace: conjugate :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs (Complex e)
- Graphics.Image.ColorSpace: fromDouble :: (Elevator e, ColorSpace cs) => Pixel cs Double -> Pixel cs e
+ Graphics.Image.ColorSpace: fromDouble :: Elevator e => Double -> e
- Graphics.Image.ColorSpace: imagPart :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs e
+ Graphics.Image.ColorSpace: imagPart :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs e
- Graphics.Image.ColorSpace: magnitude :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs e
+ Graphics.Image.ColorSpace: magnitude :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs e
- Graphics.Image.ColorSpace: mkPolar :: (ColorSpace cs, RealFloat e) => Pixel cs e -> Pixel cs e -> Pixel cs (Complex e)
+ Graphics.Image.ColorSpace: mkPolar :: (Applicative (Pixel cs), RealFloat e) => Pixel cs e -> Pixel cs e -> Pixel cs (Complex e)
- Graphics.Image.ColorSpace: phase :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs e
+ Graphics.Image.ColorSpace: phase :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs e
- Graphics.Image.ColorSpace: polar :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> (Pixel cs e, Pixel cs e)
+ Graphics.Image.ColorSpace: polar :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> (Pixel cs e, Pixel cs e)
- Graphics.Image.ColorSpace: realPart :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs e
+ Graphics.Image.ColorSpace: realPart :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs e
- Graphics.Image.ColorSpace: toDouble :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Double
+ Graphics.Image.ColorSpace: toDouble :: Elevator e => e -> Double
- Graphics.Image.ColorSpace: toFloat :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Float
+ Graphics.Image.ColorSpace: toFloat :: Elevator e => e -> Float
- Graphics.Image.ColorSpace: toPixelBinary :: (ColorSpace cs, Eq (Pixel cs e), Num e) => Pixel cs e -> Pixel Binary Bit
+ Graphics.Image.ColorSpace: toPixelBinary :: (Eq (Pixel cs e), Num (Pixel cs e)) => Pixel cs e -> Pixel Binary Bit
- Graphics.Image.ColorSpace: toWord16 :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Word16
+ Graphics.Image.ColorSpace: toWord16 :: Elevator e => e -> Word16
- Graphics.Image.ColorSpace: toWord32 :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Word32
+ Graphics.Image.ColorSpace: toWord32 :: Elevator e => e -> Word32
- Graphics.Image.ColorSpace: toWord64 :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Word64
+ Graphics.Image.ColorSpace: toWord64 :: Elevator e => e -> Word64
- Graphics.Image.ColorSpace: toWord8 :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Word8
+ Graphics.Image.ColorSpace: toWord8 :: Elevator e => e -> Word8
- Graphics.Image.IO: readImageExact :: Readable img format => format -> FilePath -> IO (Either String img)
+ Graphics.Image.IO: readImageExact :: Readable (Image arr cs e) format => format -> FilePath -> IO (Either String (Image arr cs e))
- Graphics.Image.IO: writeImageExact :: Writable img format => format -> [SaveOption format] -> FilePath -> img -> IO ()
+ Graphics.Image.IO: writeImageExact :: Writable (Image arr cs e) format => format -> [SaveOption format] -> FilePath -> (Image arr cs e) -> IO ()
- Graphics.Image.IO.Histogram: getHistogram :: (MArray arr Gray e, Elevator e) => Image arr Gray e -> Histogram
+ Graphics.Image.IO.Histogram: getHistogram :: MArray arr Gray e => Image arr Gray e -> Histogram
- Graphics.Image.IO.Histogram: getHistograms :: forall arr cs e. (MArray arr Gray e, Array arr Gray e, MArray arr cs e, Array arr cs e, Elevator e) => Image arr cs e -> Histograms
+ Graphics.Image.IO.Histogram: getHistograms :: forall arr cs e. (ChannelColour cs, MArray arr Gray e, Array arr Gray e, MArray arr cs e, Array arr cs e) => Image arr cs e -> Histograms
- Graphics.Image.Interface: addAlpha :: Alpha cs => e -> Pixel (Opaque cs) e -> Pixel cs e
+ Graphics.Image.Interface: addAlpha :: AlphaSpace cs e => e -> Pixel (Opaque cs) e -> Pixel cs e
- Graphics.Image.Interface: class (Show arr, ColorSpace cs, Num (Pixel cs e), Functor (Pixel cs), Applicative (Pixel cs), Foldable (Pixel cs), Num e, Typeable e, Elt arr cs e) => BaseArray arr cs e where type Elt arr cs e :: Constraint data Image arr cs e type Elt arr cs e = () where {
+ Graphics.Image.Interface: class (Show arr, ColorSpace cs e, Num (Pixel cs e), SuperClass arr cs e) => BaseArray arr cs e where type SuperClass arr cs e :: Constraint data Image arr cs e type SuperClass arr cs e = () where {
- Graphics.Image.Interface: class (Eq cs, Enum cs, Show cs, Typeable cs) => ColorSpace cs where type PixelElt cs e data Pixel cs e where {
+ Graphics.Image.Interface: class (Eq cs, Enum cs, Show cs, Typeable cs, Elevator e, Typeable e) => ColorSpace cs e where type Components cs e foldrPx f !z0 !xs = foldlPx f' id xs z0 where f' k x !z = k $! f x z foldlPx f !z0 !xs = foldrPx f' id xs z0 where f' x k !z = k $! f z x foldl1Px f !xs = fromMaybe (error "foldl1: empty Pixel") (foldlPx mf Nothing xs) where mf m !y = Just (case m of { Nothing -> y Just x -> f x y }) toListPx !px = foldr' f [] (enumFrom (toEnum 0)) where f !cs !ls = getPxC px cs : ls where {
- Graphics.Image.Interface: class BaseArray arr cs e => MArray arr cs e where data MImage st arr cs e index !img !ix = borderIndex (error $ show img ++ " - Index out of bounds: " ++ show ix) img ix where {
+ Graphics.Image.Interface: class BaseArray arr cs e => MArray arr cs e where data MImage s arr cs e index !img !ix = borderIndex (error $ show img ++ " - Index out of bounds: " ++ show ix) img ix where {
- Graphics.Image.Interface: data family MImage st arr cs e;
+ Graphics.Image.Interface: data family MImage s arr cs e;
- Graphics.Image.Interface: dropAlpha :: Alpha cs => Pixel cs e -> Pixel (Opaque cs) e
+ Graphics.Image.Interface: dropAlpha :: AlphaSpace cs e => Pixel cs e -> Pixel (Opaque cs) e
- Graphics.Image.Interface: fromDouble :: (Elevator e, ColorSpace cs) => Pixel cs Double -> Pixel cs e
+ Graphics.Image.Interface: fromDouble :: Elevator e => Double -> e
- Graphics.Image.Interface: getAlpha :: Alpha cs => Pixel cs e -> e
+ Graphics.Image.Interface: getAlpha :: AlphaSpace cs e => Pixel cs e -> e
- Graphics.Image.Interface: mdims :: MArray arr cs e => MImage st arr cs e -> (Int, Int)
+ Graphics.Image.Interface: mdims :: MArray arr cs e => MImage s arr cs e -> (Int, Int)
- Graphics.Image.Interface: toDouble :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Double
+ Graphics.Image.Interface: toDouble :: Elevator e => e -> Double
- Graphics.Image.Interface: toFloat :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Float
+ Graphics.Image.Interface: toFloat :: Elevator e => e -> Float
- Graphics.Image.Interface: toWord16 :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Word16
+ Graphics.Image.Interface: toWord16 :: Elevator e => e -> Word16
- Graphics.Image.Interface: toWord32 :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Word32
+ Graphics.Image.Interface: toWord32 :: Elevator e => e -> Word32
- Graphics.Image.Interface: toWord64 :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Word64
+ Graphics.Image.Interface: toWord64 :: Elevator e => e -> Word64
- Graphics.Image.Interface: toWord8 :: (Elevator e, ColorSpace cs) => Pixel cs e -> Pixel cs Word8
+ Graphics.Image.Interface: toWord8 :: Elevator e => e -> Word8
- Graphics.Image.Interface.Repa: toRepaArray :: (Array arr cs e, Array RS cs e, Exchangable arr RS) => Image arr cs e -> Array U DIM2 (Pixel cs e)
+ Graphics.Image.Interface.Repa: toRepaArray :: (Array arr cs e, Array RSU cs e, Exchangable arr RSU) => Image arr cs e -> Array U DIM2 (Pixel cs e)
- Graphics.Image.Processing: interpolate :: (Interpolation method, Elevator e, Num e, ColorSpace cs) => method -> Border (Pixel cs e) -> (Int, Int) -> ((Int, Int) -> Pixel cs e) -> (Double, Double) -> Pixel cs e
+ Graphics.Image.Processing: interpolate :: (Interpolation method, Num (Pixel cs e), ColorSpace cs e) => method -> Border (Pixel cs e) -> (Int, Int) -> ((Int, Int) -> Pixel cs e) -> (Double, Double) -> Pixel cs e
- Graphics.Image.Processing: pixelGrid :: (Array arr cs e, Elevator e) => Word8 -> Image arr cs e -> Image arr cs e
+ Graphics.Image.Processing: pixelGrid :: Array arr cs e => Word8 -> Image arr cs e -> Image arr cs e
- Graphics.Image.Processing: resize :: (Interpolation method, Array arr cs e, Elevator e) => method -> Border (Pixel cs e) -> (Int, Int) -> Image arr cs e -> Image arr cs e
+ Graphics.Image.Processing: resize :: (Interpolation method, Array arr cs e) => method -> Border (Pixel cs e) -> (Int, Int) -> Image arr cs e -> Image arr cs e
- Graphics.Image.Processing: rotate :: (Array arr cs e, Elevator e, Interpolation method) => method -> Border (Pixel cs e) -> Double -> Image arr cs e -> Image arr cs e
+ Graphics.Image.Processing: rotate :: (Array arr cs e, Interpolation method) => method -> Border (Pixel cs e) -> Double -> Image arr cs e -> Image arr cs e
- Graphics.Image.Processing: scale :: (Interpolation method, Array arr cs e, Elevator e) => method -> Border (Pixel cs e) -> (Double, Double) -> Image arr cs e -> Image arr cs e
+ Graphics.Image.Processing: scale :: (Interpolation method, Array arr cs e) => method -> Border (Pixel cs e) -> (Double, Double) -> Image arr cs e -> Image arr cs e
- Graphics.Image.Processing.Binary: compareWith :: (Array arr cs e1, Array arr cs e2, Array arr Binary Bit) => Pixel cs (e1 -> e2 -> Bool) -> Image arr cs e1 -> Image arr cs e2 -> Image arr Binary Bit
+ Graphics.Image.Processing.Binary: compareWith :: (Applicative (Pixel cs), Foldable (Pixel cs), Array arr cs e1, Array arr cs e2, Array arr Binary Bit) => Pixel cs (e1 -> e2 -> Bool) -> Image arr cs e1 -> Image arr cs e2 -> Image arr Binary Bit
- Graphics.Image.Processing.Binary: thresholdWith :: (Array arr cs e, Array arr Binary Bit) => Pixel cs (e -> Bool) -> Image arr cs e -> Image arr Binary Bit
+ Graphics.Image.Processing.Binary: thresholdWith :: (Applicative (Pixel cs), Foldable (Pixel cs), Array arr cs e, Array arr Binary Bit) => Pixel cs (e -> Bool) -> Image arr cs e -> Image arr Binary Bit
- Graphics.Image.Processing.Complex: (!+!) :: (Array arr cs e, Array arr cs (Complex e)) => Image arr cs e -> Image arr cs e -> Image arr cs (Complex e)
+ Graphics.Image.Processing.Complex: (!+!) :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e)) => Image arr cs e -> Image arr cs e -> Image arr cs (Complex e)
- Graphics.Image.Processing.Complex: applyFilter :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) => Image arr cs e -> Image arr cs e -> Image arr cs e
+ Graphics.Image.Processing.Complex: applyFilter :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), Fractional (Pixel cs (Complex e)), Floating (Pixel cs e), RealFloat e) => Image arr cs e -> Image arr cs e -> Image arr cs e
- Graphics.Image.Processing.Complex: fft :: (Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs (Complex e)
+ Graphics.Image.Processing.Complex: fft :: (Applicative (Pixel cs), Array arr cs (Complex e), Fractional (Pixel cs (Complex e)), Floating (Pixel cs e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs (Complex e)
- Graphics.Image.Processing.Complex: ifft :: (Array arr cs (Complex e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs (Complex e)
+ Graphics.Image.Processing.Complex: ifft :: (Applicative (Pixel cs), Array arr cs (Complex e), Fractional (Pixel cs (Complex e)), Floating (Pixel cs e), RealFloat e) => Image arr cs (Complex e) -> Image arr cs (Complex e)
- Graphics.Image.Types: class BaseArray arr cs e => MArray arr cs e where data MImage st arr cs e index !img !ix = borderIndex (error $ show img ++ " - Index out of bounds: " ++ show ix) img ix where {
+ Graphics.Image.Types: class BaseArray arr cs e => MArray arr cs e where data MImage s arr cs e index !img !ix = borderIndex (error $ show img ++ " - Index out of bounds: " ++ show ix) img ix where {
- Graphics.Image.Types: data family MImage st arr cs e;
+ Graphics.Image.Types: data family MImage s arr cs e;

Files

CHANGELOG.md view
@@ -1,3 +1,21 @@+1.4.0.0+=======++Major rewrite, with most of functionality is still backwards compatible, but+with a some extra features.++* Storable Repa and Vector representations through generic implementations+* `ColorSpace` is more general allowing for non polymorphic Pixel types+* `Elevator` works on base types rather than on pixels+* Conversions from JuicyPixels and NetPbm is done through casting a Vector+  rather than through an explicit conversion.++Major API changes:++  * Renaming `RS` and `RP` Repa representations into `RSU` and `RPU`.+  * Addition `VS` Storable Vector representationas well as `RSS` and `RPS`+    Storable Repa representations.+     1.3.0.0 ======= 
README.md view
@@ -19,7 +19,7 @@  * `$ stack install hip` -In order to be able to view images in GHCi and external image viewer is used. On-Linux I recommend `GPicView`, but you can use any viewer that accepts a filename-as an argument, so by default OS specific image viewer is used.+In order to be able to view images in GHCi an external image viewer is used. You+can use any viewer that accepts a filename as an argument, and by default, image+viewer specified by the OS is used. 
+ benchmarks/Canny.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE BangPatterns #-}+module Main where++import Prelude as P+import Criterion.Main+import Graphics.Image as I+import Graphics.Image.Interface as I+import Graphics.Image.Interface.Repa+++import Data.Array.Repa as R+import Data.Array.Repa.Eval+import Data.Array.Repa.Repr.Unboxed+import Data.Array.Repa.Stencil+import Data.Array.Repa.Stencil.Dim2+++sobelGx :: I.Array arr cs e => Image arr cs e -> Image arr cs e+sobelGx =+  convolve Edge (fromLists [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])++sobelGy :: I.Array arr cs e => Image arr cs e -> Image arr cs e+sobelGy =+  convolve Edge (fromLists [[-1,-2,-1], [ 0, 0, 0], [ 1, 2, 1]])++-- sobelSGx :: (Exchangable arr VS, I.Array arr cs e, I.Array VS cs e) => Image arr cs e -> Image arr cs e+-- sobelSGx =+--   convolveSparse Edge (fromLists [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])++-- sobelSGy :: (Exchangable arr VS, I.Array arr cs e, I.Array VS cs e) => Image arr cs e -> Image arr cs e+-- sobelSGy =+--   convolveSparse Edge (fromLists [[-1,-2,-1], [ 0, 0, 0], [ 1, 2, 1]])+++-- sobelSGx' :: (Exchangable arr VS, I.Array arr cs e, I.Array VS cs e) => Image arr cs e -> Image arr cs e+-- sobelSGx' =+--   convolveSparse Edge (fromLists [[1], [2], [1]]) . convolveSparse Edge (fromLists [[1, 0, -1]])++sobelGx' :: I.Array arr cs e => Image arr cs e -> Image arr cs e+sobelGx' =+  convolveCols Edge [1, 2, 1] . convolveRows Edge [1, 0, -1]++sobelGy' :: I.Array arr cs e => Image arr cs e -> Image arr cs e+sobelGy' =+  convolveCols Edge [1, 0, -1] . convolveRows Edge [1, 2, 1]+++sobelGxR+  :: (Source r e, Num e) => R.Array r DIM2 e+     -> R.Array PC5 DIM2 e+sobelGxR = mapStencil2 BoundClamp stencil +  where stencil = makeStencil2 3 3+                  (\ix -> case ix of+                      Z :. -1 :. -1  -> Just (-1)+                      Z :.  0 :. -1  -> Just (-2)+                      Z :.  1 :. -1  -> Just (-1)+                      Z :. -1 :.  1  -> Just 1+                      Z :.  0 :.  1  -> Just 2+                      Z :.  1 :.  1  -> Just 1+                      _              -> Nothing)++sobelGyR+  :: (Source r e, Num e) => R.Array r DIM2 e+     -> R.Array PC5 DIM2 e+sobelGyR = mapStencil2 BoundClamp stencil +  where stencil = makeStencil2 3 3+                  (\ix -> case ix of+                      Z :.  1 :. -1  -> Just (-1)+                      Z :.  1 :.  0  -> Just (-2)+                      Z :.  1 :.  1  -> Just (-1)+                      Z :. -1 :. -1  -> Just 1+                      Z :. -1 :.  0  -> Just 2+                      Z :. -1 :.  1  -> Just 1+                      _              -> Nothing)++force+  :: (Load r1 sh e, Unbox e, Monad m)+  => R.Array r1 sh e -> m (R.Array U sh e)+force arr = do+    forcedArr <- computeUnboxedP arr+    forcedArr `deepSeqArray` return forcedArr++++main :: IO ()+main = do+  img' <- readImageRGB RPU "images/downloaded/frog-1280x824.jpg"+  let !imgU = compute img'+  --let !imgS = exchange RPS imgU+  let sobelU = sobelGx imgU+  let sobelSepU = sobelGx' imgU+  -- let sobelS = sobelGx imgS+  -- let sobelSepS = sobelGx' imgS+  -- let sobelSepVS = sobelSGx' img+  -- let sobelVS = sobelSGx img+  -- let sobelMS = sobelMSGx img+  -- let sobelIMS = sobelIMSGx img+  -- let sobelHMS = sobelHMSGx img+  let !imgR = toRepaArray imgU+  --imgRDouble <- force $ R.map (`getPxCh` Y) imgR+  let sobelR = sobelGxR imgR+  --let sobelRDouble = sobelGxR imgRDouble+  defaultMain+    [ bgroup+        "Sobel"+        [ bench "naive U" $ whnf compute sobelU+        , bench "separated U" $ whnf compute sobelSepU+        -- , bench "naive S" $ whnf compute sobelS+        -- , bench "separated S" $ whnf compute sobelSepS+        -- , bench "separated VS" $ whnf compute sobelSepVS+        -- , bench "sparse VS" $ whnf compute sobelVS+        -- , bench "sparse MS" $ whnf compute sobelMS+        -- , bench "sparse IMS" $ whnf compute sobelIMS+        -- , bench "sparse HMS" $ whnf compute sobelHMS+        --, bench "repa" $ whnf (compute . fromRepaArrayP) sobelR+        , bench "repa RGB" $ whnfIO (force sobelR)+        --, bench "repa Double" $ whnfIO (force sobelRDouble)+        ]+    ]+  -- img' <- readImageY RS "images/downloaded/frog-1280x824.jpg"+  -- let !imgR = compute img'+  -- let !imgV = toManifest imgR+  -- -- let sobel = sobelGx imgV+  -- -- let sobel' = sobelGx' imgV+  -- -- let sobel'' = sobelSGx imgV+  -- let arrR = toRepaArray imgR+  -- let sobelR = sobelGxR arrR+  -- defaultMain+  --   [ bgroup+  --       "Sobel"+  --       [ bench "naive" $ nf sobelGx imgV+  --       , bench "separated" $ nf sobelGx' imgV+  --       , bench "sparse" $ nf sobelSGx imgV+  --       --, bench "repa" $ whnf (compute . fromRepaArrayP) sobelR+  --       , bench "repa" $ whnfIO (force sobelR)+  --       ]+  --   ]++  -- let sobel = sqrt (sobelGx img ^ (2 :: Int) + sobelGy img ^ (2 :: Int))+  -- let sobel' = sqrt (sobelGx' img ^ (2 :: Int) + sobelGy' img ^ (2 :: Int))+  -- let sobel'' = sqrt (sobelSGx img ^ (2 :: Int) + sobelSGy img ^ (2 :: Int))+  -- let sobel''' = sqrt (sobelMSGx img ^ (2 :: Int) + sobelMSGy img ^ (2 :: Int))+  -- let imgR = toRepaArray img+  -- let sobelR =+  --       R.map+  --         sqrt+  --         (R.map (^ (2 :: Int)) (sobelGxR imgR) +^+  --          R.map (^ (2 :: Int)) (sobelGyR imgR))+  -- defaultMain+  --   [ bgroup+  --       "Sobel"+  --       [ bench "naive" $ whnf compute sobel+  --       , bench "separated" $ whnf compute sobel'+  --       , bench "sparse VS" $ whnf compute sobel''+  --       , bench "sparse MS" $ whnf compute sobel'''+  --       --, bench "repa" $ whnf (compute . fromRepaArrayP) sobelR+  --       , bench "repa" $ whnfIO (force sobelR)+  --       ]+  --   ]+
− benchmarks/Interface.hs
@@ -1,75 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-module Main where--import Prelude as P-import Criterion.Main-import Graphics.Image.Interface as I---import Graphics.Image.Processing----import qualified Graphics.Image.Interface.Vector as V-import Graphics.Image.Types--main :: IO ()-main = do-  defaultMain-    [ bgroup-        "RP fusion"-        [ bench "native" $-          whnf-            (compute  . (noFusion :: (Int, Int) -> Image RP Y Double))-            (1000, 1000)-        , bench "RP fusion" $-          whnf-            (compute  . (fusion :: (Int, Int) -> Image RP Y Double))-            (1000, 1000)-        ]-    , bgroup-        "RS fusion"-        [ bench "native" $-          whnf-            (compute . (noFusion :: (Int, Int) -> Image RS Y Double))-            (1000, 1000)-        , bench "RS fusion" $-          whnf-            (compute . (fusion :: (Int, Int) -> Image RS Y Double))-            (1000, 1000)-        ]-    , bgroup-        "VU fusion"-        [ bench "no fusion" $-          nf (noFusion :: (Int, Int) -> Image VU Y Double) (1000, 1000)-        , bench "VU fusion" $-          nf (fusion :: (Int, Int) -> Image VU Y Double) (1000, 1000)-        ]-    ]---frog <- V.readImageY "images/frog.jpg"---     [ bgroup---         ("makeImage big " ++ show bigDims)---         [ bench "makeImage VU" $ nf (`V.makeImage` getPxY) bigDims---         , bench "computeS" $ nf R.computeS (R.makeImage bigDims getPxY)---           -- parallel---         , bench "computeP" $ nf R.computeP (R.makeImage bigDims getPxY)---         ]---     , bgroup---         "Sobel operator"---         [ bench "sobel VU" $ nf sobel frog---         , bench "sobel RS" $ nf (sobel . exchange RS) frog---           -- parallel---         , bench "sobel RP" $ nf (sobel . R.computeP . exchange RP) frog---         ]---     ]-    where---     bigDims = (2000, 2000)-      getPxY :: (Int, Int) -> Pixel Y Double-      getPxY (i, j) = fromIntegral (i * j)-      noFusion ds = makeImage ds getPx-        where getPx :: (Int, Int) -> Pixel Y Double-              getPx (i, j) = (getPxY (i, j) / 5 - fromIntegral i) * 21-      fusion ds = imap (\ (i, _) px -> (px - fromIntegral i) * 21) $ (makeImage ds getPxY / 5)----- sobel :: ManifestArray arr cs Double => Image arr cs Double -> Image arr cs Double--- sobel img = sqrt (imgX ^ (2 :: Int) + imgY ^ (2 :: Int))---   where---     imgX = convolve Edge (fromLists [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) img---     imgY = convolve Edge (fromLists [[-1,-2,-1], [ 0, 0, 0], [ 1, 2, 1]]) img
hip.cabal view
@@ -1,5 +1,5 @@ Name:              hip-Version:           1.3.0.0+Version:           1.4.0.0 License:           BSD3 License-File:      LICENSE Author:            Alexey Kuleshevich@@ -76,7 +76,12 @@                  , Graphics.Image.IO.Base                  , Graphics.Image.IO.Formats.JuicyPixels                  , Graphics.Image.IO.Formats.Netpbm-                 , Graphics.Image.Interface.Repa.Internal+                 , Graphics.Image.Interface.Repa.Generic+                 , Graphics.Image.Interface.Repa.Storable+                 , Graphics.Image.Interface.Repa.Unboxed+                 , Graphics.Image.Interface.Repa.Helpers+                 , Graphics.Image.Interface.Vector.Generic+                 , Graphics.Image.Interface.Vector.Storable                  , Graphics.Image.Interface.Vector.Unboxed                  , Graphics.Image.Interface.Vector.Unboxing                  , Graphics.Image.Processing.Convolution@@ -99,6 +104,7 @@   Main-Is:            Spec.hs   Other-Modules:      Graphics.Image.ColorSpaceSpec                     , Graphics.Image.ProcessingSpec+                    , Graphics.Image.Processing.BinarySpec                     , Graphics.Image.InterfaceSpec                     , Graphics.Image.Interface.VectorSpec   Build-Depends:      base            >= 4.5 && < 5@@ -109,16 +115,56 @@   GHC-Options:        -Wall -threaded -with-rtsopts=-N  -benchmark interface-benchmarks+-- benchmark pixels-benchmarks+--   type:                exitcode-stdio-1.0+--   hs-source-dirs:      benchmarks+--   main-is:             Pixels.hs+--   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -O2+--   build-depends:       base+--                      , criterion+--                      , deepseq+--                      , hip+--                      , vector+--   default-language:    Haskell2010++-- benchmark pixels-memory+--   type:                exitcode-stdio-1.0+--   hs-source-dirs:      benchmarks/memory+--   main-is:             Pixels.hs+--   ghc-options:         -O2+--                        -- -threaded -rtsopts -with-rtsopts=-N+--   build-depends:       base+--                      , criterion+--                      , deepseq+--                      , hip+--                      , weigh+--                      , vector+--                      , repa+--   default-language:    Haskell2010++-- benchmark interface-benchmarks+--   type:                exitcode-stdio-1.0+--   hs-source-dirs:      benchmarks+--   main-is:             Interface.hs+--   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -O2+--   build-depends:       base+--                      , criterion+--                      , deepseq+--                      , hip+--                      , vector+--   default-language:    Haskell2010++benchmark convolution-benchmarks   type:                exitcode-stdio-1.0   hs-source-dirs:      benchmarks-  main-is:             Interface.hs-  ghc-options:         -threaded -rtsopts -with-rtsopts=-N+  main-is:             Canny.hs+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -O2+  --ghc-options:         -Odph -rtsopts -with-rtsopts=-N -threaded -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000 -fllvm -optlo-O3   build-depends:       base                      , criterion                      , deepseq+                     , repa                      , hip-                     , vector   default-language:    Haskell2010  Source-Repository head
images/figure_close.png view

binary file changed (384 → 382 bytes)

images/figure_dialate.png view

binary file changed (390 → 395 bytes)

images/figure_erode.png view

binary file changed (411 → 414 bytes)

images/figure_open.png view

binary file changed (404 → 409 bytes)

images/struct.png view

binary file changed (94 → 102 bytes)

src/Graphics/Image.hs view
@@ -1,6 +1,5 @@ {-# OPTIONS_GHC -fno-warn-unused-imports #-} {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} -- | -- Module      : Graphics.Image@@ -18,11 +17,11 @@ -- * @__`Array` arr cs e__@ - this is a base class for every -- __@`Image`@ @arr@ @cs@ @e@__, where @__arr__@ stands for an underlying array -- representation, @__cs__@ is the `ColorSpace` of an image and @__e__@ is the--- type denoting precision of an image.+-- type denoting precision of an image (@Int@, @Word@, @Double@, etc.) . -- -- * @__`MArray` arr cs e__@ - is a kind of array, that can be indexed in--- constant time and allows monadic operations and mutation on __@`MImage`@ @st@--- @arr@ @cs@ @e@__, which is `Image`'s mutable cousin.+-- constant time and allows monadic operations and mutation on+-- __@`MImage`@ @st@ @arr@ @cs@ @e@__, which is `Image`'s mutable cousin. -- -- Array representation type and the above classes it is installed in determine -- operations that can be done on the image with that representation.@@ -30,27 +29,25 @@ -- Representations using <http://hackage.haskell.org/package/vector Vector> and -- <http://hackage.haskell.org/package/repa Repa> packages: ----- * `VU` - Unboxed Vector representation. (Default)--- * `RS` - Unboxed Repa array representation (computation is done sequentially).--- * `RP` - Unboxed Repa array representation (computation is done in parallel).+-- * `VU` - Vector Unboxed representation.+-- * `VS` - Vector Storable representation.+-- * `RSU` - Repa Sequential Unboxed array representation (computation is done sequentially).+-- * `RPU` - Repa Parallel Unboxed array representation (computation is done in parallel).+-- * `RSS` - Repa Sequential Storable array representation (computation is done sequentially).+-- * `RPS` - Repa Parallel Storable array representation (computation is done in parallel). ----- Images with `RS` and `RP` types, most of the time hold functions rather then+-- Images with `RSU` and `RPU` types, most of the time hold functions rather then -- actual data, this way computation can be fused together, and later changed to -- `VU` using `toManifest`, which in turn performs the fused computation. If at -- any time computation needs to be forced, `compute` can be used for that -- purpose. ----- Just as it is mentioned above, Vector representation is a default one, so in--- order to create images with Repa representation--- "Graphics.Image.Interface.Repa" module should be used.--- -- Many of the function names exported by this module will clash with the ones--- from "Prelude", hence it can be more convenient to import it qualified and--- all relevenat types import using "Graphics.Image.Types" module:+-- from "Prelude", hence it can be more convenient to import like this: -- -- @--- import qualified Graphics.Image as I--- import Graphics.Image.Types+-- import Prelude as P+-- import Graphics.Image as I -- @ -- module Graphics.Image (@@ -59,14 +56,17 @@    -- * Creation   ---  -- If it is necessary to create an image in an other representation-  -- or with some specific 'Pixel' precision, you can use 'make' from-  -- "Graphics.Image.Interface" module and manually specifying function's output-  -- type, ex:+  -- `makeImageR` is a type restricted version of `makeImage` function, which+  -- simplifies creation of images with `Double` precision and a particular+  -- representation through an extra argument.   ---  -- @ makeImage (256, 256) (PixelY . fromIntegral . fst) :: Image RP Y Word8 @+  -- If it is necessary to create an image with an arbitrary precision and+  -- representation, `makeImage` function can be used with a manual type+  -- specification of result image, eg:   ---  makeImage, makeImageS, makeImageP, fromLists, fromListsS, fromListsP, toLists,+  -- @ makeImage (256, 256) (PixelY . fromIntegral . fst) :: Image RPU Y Word8 @+  --+  makeImageR, makeImage, fromListsR, fromLists, toLists,   -- * IO   -- ** Reading   -- | Read supported files into an 'Image' with pixels in 'Double'@@ -74,15 +74,15 @@   -- space or precision, use 'readImage' or 'readImageExact' from   -- <Graphics-Image-IO.html Graphics.Image.IO> instead. While reading an   -- image, it's underlying representation can be specified by passing one of-  -- `VU`, `RS` or `RP` as the first argument to @readImage*@ functions. Here is+  -- `VU`, `RSU` or `RPU` as the first argument to @readImage*@ functions. Here is   -- a quick demonstration of how two images can be read as different   -- representations and later easily combined as their average.   ---  -- >>> cluster <- readImageRGB RP "images/cluster.jpg"+  -- >>> cluster <- readImageRGB RPU "images/cluster.jpg"   -- >>> displayImage cluster   -- >>> centaurus <- readImageRGB VU "images/centaurus.jpg"   -- >>> displayImage centaurus-  -- >>> displayImage ((cluster + exchange RP centaurus) / 2)+  -- >>> displayImage ((cluster + exchange RPU centaurus) / 2)   --   -- <<images/cluster.jpg>> <<images/centaurus.jpg>> <<images/centaurus_and_cluster.jpg>>   --@@ -96,38 +96,60 @@   index, maybeIndex, defaultIndex, borderIndex,   -- * Transformation   -- ** Pointwise-  map, imap, zipWith, izipWith,+  I.map, imap, I.zipWith, izipWith,   -- ** Geometric-  traverse, traverse2,+  I.traverse, traverse2,   transpose, backpermute,   (|*|),    -- * Reduction   fold, sum, product, maximum, minimum, normalize,   -- * Representations   exchange,-  VU(..), RS(..), RP(..),+  module IP   ) where -#if MIN_VERSION_base(4,8,0)-import Prelude hiding (map, zipWith, sum, product, maximum, minimum, traverse)-#else-import Prelude hiding (map, zipWith, sum, product, maximum, minimum)-import Control.Applicative (pure)-#endif+import Prelude as P hiding (maximum, minimum, sum, product) import qualified Data.Foldable as F import Graphics.Image.ColorSpace import Graphics.Image.IO-import Graphics.Image.Interface as I hiding (makeImage, fromLists)-import Graphics.Image.Interface.Vector-import Graphics.Image.Interface.Repa+import Graphics.Image.Interface as I+import Graphics.Image.Types as IP +import Graphics.Image.Processing as IP+import Graphics.Image.Processing.Binary as IP+import Graphics.Image.Processing.Complex as IP+import Graphics.Image.Processing.Geometric as IP+import Graphics.Image.IO.Histogram as IP -import Graphics.Image.Processing-import Graphics.Image.Processing.Binary-import Graphics.Image.Processing.Complex-import Graphics.Image.Processing.Geometric-import Graphics.Image.IO.Histogram +-- | Create an image with a specified representation and pixels of 'Double'+-- precision. Note, that it is essential for 'Double' precision pixels to keep values+-- normalized in the @[0, 1]@ range in order for an image to be written to file+-- properly.+--+-- >>> let grad_gray = makeImageR VU (200, 200) (\(i, j) -> PixelY (fromIntegral i) / 200 * (fromIntegral j) / 200)+--+-- Because all 'Pixel's and 'Image's are installed into 'Num', above is equivalent to:+--+-- >>> let grad_gray = makeImageR RPU (200, 200) (\(i, j) -> PixelY $ fromIntegral (i*j)) / (200*200)+-- >>> writeImage "images/grad_gray.png" grad_gray+--+-- Creating color images is just as easy.+--+-- >>> let grad_color = makeImageR VU (200, 200) (\(i, j) -> PixelRGB (fromIntegral i) (fromIntegral j) (fromIntegral (i + j))) / 400+-- >>> writeImage "images/grad_color.png" grad_color+--+-- <<images/grad_gray.png>> <<images/grad_color.png>>+--+makeImageR :: Array arr cs Double =>+              arr -- ^ Underlying image representation.+           -> (Int, Int) -- ^ (@m@ rows, @n@ columns) - dimensions of a new image.+           -> ((Int, Int) -> Pixel cs Double)+           -- ^ A function that takes (@i@-th row, and @j@-th column) as an argument+           -- and returns a pixel for that location.+           -> Image arr cs Double+makeImageR _ = I.makeImage+{-# INLINE makeImageR #-}  -- | Read image as luma (brightness). readImageY :: Array arr Y Double => arr -> FilePath -> IO (Image arr Y Double)@@ -204,18 +226,24 @@   -- | Scales all of the pixels to be in the range @[0, 1]@.-normalize :: (Array arr cs e, Array arr Gray e, Fractional e, Ord e) =>+normalize :: (Array arr cs e, Array arr Gray e, Fractional e,+              Fractional (Pixel cs e), Ord e) =>              Image arr cs e -> Image arr cs e normalize !img = if l == s                  then (if s < 0 then (*0) else if s > 1 then (*1) else id) img-                 else map normalizer img+                 else I.map normalizer img   where-    !(PixelGray l, PixelGray s) = (maximum $ map (PixelGray . F.maximum) img,-                                   minimum $ map (PixelGray . F.minimum) img)-    normalizer !px = (px - pure s) / pure (l - s)+    !(PixelGray l, PixelGray s) = (maximum (I.map (PixelGray . foldl1Px max) img),+                                   minimum (I.map (PixelGray . foldl1Px min) img))+    normalizer !px = (px - broadcastC s) / broadcastC (l - s)     {-# INLINE normalizer #-} {-# INLINE normalize #-} ++-- | Type restricted version of `fromLists` that constructs an image using+-- supplied representation.+fromListsR :: Array arr cs e => arr -> [[Pixel cs e]] -> Image arr cs e+fromListsR _ = fromLists  -- | Generates a nested list of pixels from an image. --
src/Graphics/Image/ColorSpace.hs view
@@ -3,9 +3,10 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} -- | -- Module      : Graphics.Image.ColorSpace--- Copyright   : (c) Alexey Kuleshevich 2016+-- Copyright   : (c) Alexey Kuleshevich 2017 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -13,7 +14,7 @@ -- module Graphics.Image.ColorSpace (   -- * ColorSpace-  ColorSpace, Pixel(..), Alpha, Opaque, Elevator(..),+  ColorSpace, Pixel(..), AlphaSpace(..), Elevator(..),   -- * Luma   module Graphics.Image.ColorSpace.Luma,   -- * RGB@@ -36,6 +37,7 @@   ) where  import Data.Word+import Data.Int import GHC.Float import Graphics.Image.Interface hiding (map) import Graphics.Image.ColorSpace.Binary@@ -49,11 +51,11 @@ import qualified Graphics.Image.Interface as I (map)  - -- Binary:  -- | Convert any pixel to binary pixel.-toPixelBinary :: (ColorSpace cs, Eq (Pixel cs e), Num e) => Pixel cs e -> Pixel Binary Bit+toPixelBinary :: (Eq (Pixel cs e), Num (Pixel cs e))+                 => Pixel cs e -> Pixel Binary Bit toPixelBinary px = if px == 0 then on else off {-# INLINE toPixelBinary #-} @@ -111,7 +113,7 @@ instance ToYA YCbCrA where    instance ToRGB Y where-  toPixelRGB (PixelY g) = fromChannel g+  toPixelRGB (PixelY g) = broadcastC g   {-# INLINE toPixelRGB #-}  instance ToRGBA YA where@@ -125,6 +127,7 @@     getThird !v1 !v2 = i + 2*is + v1 - v2     {-# INLINE getThird #-}     getRGB h+      | h < 0      = error ("HSI pixel is not properly scaled, Hue: "++show h')       | h < 2*pi/3 = let !r = getFirst h (pi/3 - h)                          !b = second                          !g = getThird b r@@ -205,216 +208,244 @@  instance ToCMYKA RGBA where -  --- | Values are scaled to @[0, 255]@ range.++dropDown :: forall a b. (Integral a, Bounded a, Integral b, Bounded b) => a -> b+dropDown !e = fromIntegral $ fromIntegral e `div` ((maxBound :: a) `div`+                                                   fromIntegral (maxBound :: b)) +{-# INLINE dropDown #-}++raiseUp :: forall a b. (Integral a, Bounded a, Integral b, Bounded b) => a -> b+raiseUp !e = fromIntegral e * ((maxBound :: b) `div` fromIntegral (maxBound :: a))+{-# INLINE raiseUp #-}+++squashTo1 :: forall a b. (Fractional b, Integral a, Bounded a) => a -> b+squashTo1 !e = fromIntegral e / fromIntegral (maxBound :: a)+{-# INLINE squashTo1 #-}++stretch :: forall a b. (RealFrac a, Floating a, Integral b, Bounded b) => a -> b+stretch !e = round (fromIntegral (maxBound :: b) * clamp01 e)+++-- | Clamp a value to @[0, 1]@ range.+clamp01 :: (Ord a, Floating a) => a -> a+clamp01 !x = min (max 0 x) 1+{-# INLINE clamp01 #-}++ instance Elevator Word8 where    toWord8 = id   {-# INLINE toWord8 #-}--  toWord16 = fmap toWord16' where-    toWord16' !e = fromIntegral e * ((maxBound :: Word16) `div` fromIntegral (maxBound :: Word8)) -    {-# INLINE toWord16' #-}+  toWord16 = raiseUp   {-# INLINE toWord16 #-}--  toWord32 = fmap toWord32' where-    toWord32' !e = fromIntegral e * ((maxBound :: Word32) `div` fromIntegral (maxBound :: Word8)) -    {-# INLINE toWord32' #-}+  toWord32 = raiseUp   {-# INLINE toWord32 #-}--  toWord64 = fmap toWord64' where-    toWord64' !e = fromIntegral e * ((maxBound :: Word64) `div` fromIntegral (maxBound :: Word8))-    {-# INLINE toWord64' #-}+  toWord64 = raiseUp   {-# INLINE toWord64 #-}--  toFloat = fmap toFloat' where-    toFloat' !e = fromIntegral e / fromIntegral (maxBound :: Word8)-    {-# INLINE toFloat' #-}+  toFloat = squashTo1   {-# INLINE toFloat #-}--  toDouble = fmap toDouble' where-    toDouble' !e = fromIntegral e / fromIntegral (maxBound :: Word8)-    {-# INLINE toDouble' #-}+  toDouble = squashTo1   {-# INLINE toDouble #-}-   fromDouble = toWord8   {-# INLINE fromDouble #-}  --- | Values are scaled to @[0, 65535]@ range. instance Elevator Word16 where -  toWord8 = fmap toWord8' where-    toWord8' !e = fromIntegral $ fromIntegral e `div` ((maxBound :: Word16) `div`-                                                      fromIntegral (maxBound :: Word8)) -    {-# INLINE toWord8' #-}+  toWord8 = dropDown   {-# INLINE toWord8 #-}-   toWord16 = id   {-# INLINE toWord16 #-}-  -  toWord32 = fmap toWord32' where-    toWord32' !e = fromIntegral e * ((maxBound :: Word32) `div` fromIntegral (maxBound :: Word16)) -    {-# INLINE toWord32' #-}+  toWord32 = raiseUp   {-# INLINE toWord32 #-}--  toWord64 = fmap toWord64' where-    toWord64' !e = fromIntegral e * ((maxBound :: Word64) `div` fromIntegral (maxBound :: Word16))-    {-# INLINE toWord64' #-}+  toWord64 = raiseUp   {-# INLINE toWord64 #-}--  toFloat = fmap toFloat' where-    toFloat' !e = fromIntegral e / fromIntegral (maxBound :: Word16)-    {-# INLINE toFloat' #-}+  toFloat = squashTo1   {-# INLINE toFloat #-}--  toDouble = fmap toDouble' where-    toDouble' !e = fromIntegral e / fromIntegral (maxBound :: Word16)-    {-# INLINE toDouble' #-}+  toDouble = squashTo1   {-# INLINE toDouble #-}-   fromDouble = toWord16   {-# INLINE fromDouble #-}  --- | Values are scaled to @[0, 4294967295]@ range. instance Elevator Word32 where -  toWord8 = fmap toWord8' where-    toWord8' !e = fromIntegral $ fromIntegral e `div` ((maxBound :: Word32) `div`-                                                       fromIntegral (maxBound :: Word8)) -    {-# INLINE toWord8' #-}+  toWord8 = dropDown   {-# INLINE toWord8 #-}--  toWord16 = fmap toWord16' where-    toWord16' !e = fromIntegral $ fromIntegral e `div` ((maxBound :: Word32) `div`-                                                        fromIntegral (maxBound :: Word16)) -    {-# INLINE toWord16' #-}+  toWord16 = dropDown   {-# INLINE toWord16 #-}-   toWord32 = id   {-# INLINE toWord32 #-}--  toWord64 = fmap toWord64' where-    toWord64' !e = fromIntegral e * ((maxBound :: Word64) `div` fromIntegral (maxBound :: Word32))-    {-# INLINE toWord64' #-}+  toWord64 = raiseUp   {-# INLINE toWord64 #-}--  toFloat = fmap toFloat' where-    toFloat' !e = fromIntegral e / fromIntegral (maxBound :: Word32)-    {-# INLINE toFloat' #-}+  toFloat = squashTo1   {-# INLINE toFloat #-}--  toDouble = fmap toDouble' where-    toDouble' !e = fromIntegral e / fromIntegral (maxBound :: Word32)-    {-# INLINE toDouble' #-}+  toDouble = squashTo1   {-# INLINE toDouble #-}-   fromDouble = toWord32   {-# INLINE fromDouble #-}  --- | Values are scaled to @[0, 18446744073709551615]@ range. instance Elevator Word64 where -  toWord8 = fmap toWord8' where-    toWord8' !e = fromIntegral $ fromIntegral e `div` ((maxBound :: Word64) `div`-                                                       fromIntegral (maxBound :: Word8)) -    {-# INLINE toWord8' #-}+  toWord8 = dropDown   {-# INLINE toWord8 #-}--  toWord16 = fmap toWord16' where-    toWord16' !e = fromIntegral $ fromIntegral e `div` ((maxBound :: Word64) `div`-                                                        fromIntegral (maxBound :: Word16)) -    {-# INLINE toWord16' #-}+  toWord16 = dropDown   {-# INLINE toWord16 #-}--  toWord32 = fmap toWord32' where-    toWord32' !e = fromIntegral $ fromIntegral e `div` ((maxBound :: Word64) `div`-                                                        fromIntegral (maxBound :: Word32)) -    {-# INLINE toWord32' #-}+  toWord32 = dropDown   {-# INLINE toWord32 #-}-   toWord64 = id   {-# INLINE toWord64 #-}--  toFloat = fmap toFloat' where-    toFloat' !e = fromIntegral e / fromIntegral (maxBound :: Word64)-    {-# INLINE toFloat' #-}+  toFloat = squashTo1   {-# INLINE toFloat #-}--  toDouble = fmap toDouble' where-    toDouble' !e = fromIntegral e / fromIntegral (maxBound :: Word64)-    {-# INLINE toDouble' #-}+  toDouble = squashTo1   {-# INLINE toDouble #-}-   fromDouble = toWord64   {-# INLINE fromDouble #-}  --- | Values are scaled to @[0.0, 1.0]@ range.-instance Elevator Float where+instance Elevator Word where -  toWord8 = fmap toWord8' where-    toWord8' !e = round (fromIntegral (maxBound :: Word8) * e)-    {-# INLINE toWord8' #-}+  toWord8 = dropDown   {-# INLINE toWord8 #-}--  toWord16 = fmap toWord16' where-    toWord16' !e = round (fromIntegral (maxBound :: Word16) * e)-    {-# INLINE toWord16' #-}+  toWord16 = dropDown   {-# INLINE toWord16 #-}--  toWord32 = fmap toWord32' where-    toWord32' !e = round (fromIntegral (maxBound :: Word32) * e)-    {-# INLINE toWord32' #-}+  toWord32 = dropDown   {-# INLINE toWord32 #-}--  toWord64 = fmap toWord64' where-    toWord64' !e = round (fromIntegral (maxBound :: Word64) * e)-    {-# INLINE toWord64' #-}+  toWord64 = fromIntegral   {-# INLINE toWord64 #-}--  toFloat = id+  toFloat = squashTo1   {-# INLINE toFloat #-}--  toDouble = fmap float2Double+  toDouble = squashTo1   {-# INLINE toDouble #-}+  fromDouble = stretch . clamp01+  {-# INLINE fromDouble #-} -  fromDouble = toFloat++instance Elevator Int8 where++  toWord8 = fromIntegral . (max 0)+  {-# INLINE toWord8 #-}+  toWord16 = raiseUp . (max 0)+  {-# INLINE toWord16 #-}+  toWord32 = raiseUp . (max 0)+  {-# INLINE toWord32 #-}+  toWord64 = raiseUp . (max 0)+  {-# INLINE toWord64 #-}+  toFloat = squashTo1 . (max 0)+  {-# INLINE toFloat #-}+  toDouble = squashTo1 . (max 0)+  {-# INLINE toDouble #-}+  fromDouble = stretch . clamp01   {-# INLINE fromDouble #-}  --- | Values are scaled to @[0.0, 1.0]@ range.-instance Elevator Double where+instance Elevator Int16 where -  toWord8 = fmap toWord8' where-    toWord8' !e = round (fromIntegral (maxBound :: Word8) * e)-    {-# INLINE toWord8' #-}+  toWord8 = dropDown . (max 0)   {-# INLINE toWord8 #-}+  toWord16 = fromIntegral . (max 0)+  {-# INLINE toWord16 #-}+  toWord32 = raiseUp . (max 0)+  {-# INLINE toWord32 #-}+  toWord64 = raiseUp . (max 0)+  {-# INLINE toWord64 #-}+  toFloat = squashTo1 . (max 0)+  {-# INLINE toFloat #-}+  toDouble = squashTo1 . (max 0)+  {-# INLINE toDouble #-}+  fromDouble = stretch . clamp01+  {-# INLINE fromDouble #-} -  toWord16 = fmap toWord16' where-    toWord16' !e = round (fromIntegral (maxBound :: Word16) * e)-    {-# INLINE toWord16' #-}++instance Elevator Int32 where++  toWord8 = dropDown . (max 0)+  {-# INLINE toWord8 #-}+  toWord16 = dropDown . (max 0)   {-# INLINE toWord16 #-}+  toWord32 = fromIntegral . (max 0)+  {-# INLINE toWord32 #-}+  toWord64 = raiseUp . (max 0)+  {-# INLINE toWord64 #-}+  toFloat = squashTo1 . (max 0)+  {-# INLINE toFloat #-}+  toDouble = squashTo1 . (max 0)+  {-# INLINE toDouble #-}+  fromDouble = stretch . clamp01+  {-# INLINE fromDouble #-} -  toWord32 = fmap toWord32' where-    toWord32' !e = round (fromIntegral (maxBound :: Word32) * e)-    {-# INLINE toWord32' #-}++instance Elevator Int64 where++  toWord8 = dropDown . (max 0)+  {-# INLINE toWord8 #-}+  toWord16 = dropDown . (max 0)+  {-# INLINE toWord16 #-}+  toWord32 = dropDown . (max 0)   {-# INLINE toWord32 #-}+  toWord64 = fromIntegral . (max 0)+  {-# INLINE toWord64 #-}+  toFloat = squashTo1 . (max 0)+  {-# INLINE toFloat #-}+  toDouble = squashTo1 . (max 0)+  {-# INLINE toDouble #-}+  fromDouble = stretch . clamp01+  {-# INLINE fromDouble #-} -  toWord64 = fmap toWord64' where-    toWord64' !e = round (fromIntegral (maxBound :: Word64) * e)-    {-# INLINE toWord64' #-}++instance Elevator Int where++  toWord8 = dropDown . (max 0)+  {-# INLINE toWord8 #-}+  toWord16 = dropDown . (max 0)+  {-# INLINE toWord16 #-}+  toWord32 = dropDown . (max 0)+  {-# INLINE toWord32 #-}+  toWord64 = fromIntegral . (max 0)   {-# INLINE toWord64 #-}+  toFloat = squashTo1 . (max 0)+  {-# INLINE toFloat #-}+  toDouble = squashTo1 . (max 0)+  {-# INLINE toDouble #-}+  fromDouble = stretch . clamp01+  {-# INLINE fromDouble #-} -  toFloat = fmap double2Float++instance Elevator Float where+  toWord8 = stretch . clamp01+  {-# INLINE toWord8 #-}+  toWord16 = stretch . clamp01+  {-# INLINE toWord16 #-}+  toWord32 = stretch . clamp01+  {-# INLINE toWord32 #-}+  toWord64 = stretch . clamp01+  {-# INLINE toWord64 #-}+  toFloat = id   {-# INLINE toFloat #-}+  toDouble = float2Double+  {-# INLINE toDouble #-}+  fromDouble = toFloat+  {-# INLINE fromDouble #-} +instance Elevator Double where+  toWord8 = stretch . clamp01+  {-# INLINE toWord8 #-}+  toWord16 = stretch . clamp01+  {-# INLINE toWord16 #-}+  toWord32 = stretch . clamp01+  {-# INLINE toWord32 #-}+  toWord64 = stretch . clamp01+  {-# INLINE toWord64 #-}+  toFloat = double2Float+  {-# INLINE toFloat #-}   toDouble = id   {-# INLINE toDouble #-}-   fromDouble = id   {-# INLINE fromDouble #-}+++  
src/Graphics/Image/ColorSpace/Binary.hs view
@@ -2,6 +2,8 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Image.ColorSpace.Binary@@ -19,8 +21,8 @@ import Data.Word (Word8) import Graphics.Image.Interface import Data.Typeable (Typeable)-import qualified Data.Monoid as M (mappend, mempty)-import qualified Data.Colour as C+import Foreign.Ptr+import Foreign.Storable  -- | This is a Binary colorspace, pixel's of which can be created using -- these __/constructors/__:@@ -51,7 +53,13 @@ -- values of @0@ or @1@. newtype Bit = Bit Word8 deriving (Ord, Eq, Typeable) +data instance Pixel Binary e = PixelBinary !e deriving (Ord, Eq) +instance Show (Pixel Binary Bit) where+  show (PixelBinary (Bit 0)) = "<Binary:(0)>"+  show _                     = "<Binary:(1)>"++ -- | Represents value 'True' or @1@ in binary. Often also called a foreground -- pixel of an object. on :: Pixel Binary Bit@@ -96,63 +104,110 @@ {-# INLINE complement #-}  +instance ColorSpace Binary Bit where+  type Components Binary Bit = Bit -instance ColorSpace Binary where-  type PixelElt Binary e = e-  data Pixel Binary e = PixelBinary !e deriving (Ord, Eq)+  broadcastC = PixelBinary+  {-# INLINE broadcastC #-}+  fromComponents = PixelBinary+  {-# INLINE fromComponents #-}+  toComponents (PixelBinary b) = b+  {-# INLINE toComponents #-}+  getPxC (PixelBinary b) _ = b+  {-# INLINE getPxC #-}+  setPxC (PixelBinary _) _ b = PixelBinary b+  {-# INLINE setPxC #-}  +  mapPxC f (PixelBinary b) = PixelBinary (f Binary b)+  {-# INLINE mapPxC #-}+  mapPx f (PixelBinary b) = PixelBinary (f b)+  {-# INLINE mapPx #-}+  zipWithPx f (PixelBinary b1) (PixelBinary b2) = PixelBinary (f b1 b2)+  {-# INLINE zipWithPx #-}+  foldrPx f z (PixelBinary b) = f b z+  {-# INLINE foldrPx #-} -  fromChannel = PixelBinary-  {-# INLINE fromChannel #-} -  fromElt = PixelBinary-  {-# INLINE fromElt #-}--  toElt (PixelBinary b) = b-  {-# INLINE toElt #-}+instance Elevator Bit where+  toWord8 (Bit 0) = 0+  toWord8 _       = maxBound+  {-# INLINE toWord8 #-}+  toWord16 (Bit 0) = 0+  toWord16 _       = maxBound+  {-# INLINE toWord16 #-}+  toWord32 (Bit 0) = 0+  toWord32 _       = maxBound+  {-# INLINE toWord32 #-}+  toWord64 (Bit 0) = 0+  toWord64 _       = maxBound+  {-# INLINE toWord64 #-}+  toFloat (Bit 0) = 0+  toFloat _       = 1+  {-# INLINE toFloat #-}+  toDouble (Bit 0) = 0+  toDouble _       = 1+  {-# INLINE toDouble #-}+  fromDouble 0 = Bit 0+  fromDouble _ = Bit 1+  {-# INLINE fromDouble #-} -  getPxCh (PixelBinary b) _ = b-  {-# INLINE getPxCh #-}   -  chOp !f (PixelBinary b) = PixelBinary (f Binary b)-  {-# INLINE chOp #-} -  pxOp !f (PixelBinary b) = PixelBinary (f b)-  {-# INLINE pxOp #-}--  chApp (PixelBinary f) (PixelBinary b) = PixelBinary (f b)-  {-# INLINE chApp #-}--  pxFoldMap f (PixelBinary b) = f b `M.mappend` M.mempty-  {-# INLINE pxFoldMap #-}--  csColour _ = C.opaque C.black---instance Show (Pixel Binary Bit) where-  show (PixelBinary (Bit 0)) = "<Binary:(0)>"-  show _                     = "<Binary:(1)>"-- instance Num Bit where   (Bit 0) + (Bit 0) = Bit 0   _       + _       = Bit 1   {-# INLINE (+) #-}-     _ - (Bit 1) = Bit 0   _ - _       = Bit 1   {-# INLINE (-) #-}-     _       * (Bit 0) = Bit 0   (Bit 0) * _       = Bit 0   _       * _       = Bit 1   {-# INLINE (*) #-}-     abs         = id   {-# INLINE abs #-}-     signum      = id   {-# INLINE signum #-}-     fromInteger 0 = Bit 0   fromInteger _ = Bit 1   {-# INLINE fromInteger #-}+++instance Num (Pixel Binary Bit) where+  (+)         = zipWithPx (+)+  {-# INLINE (+) #-}+  (-)         = zipWithPx (-)+  {-# INLINE (-) #-}+  (*)         = zipWithPx (*)+  {-# INLINE (*) #-}+  abs         = mapPx abs+  {-# INLINE abs #-}+  signum      = mapPx signum+  {-# INLINE signum #-}+  fromInteger = broadcastC . fromInteger+  {-# INLINE fromInteger #-}+++instance Storable Bit where++  sizeOf _ = sizeOf (undefined :: Word8)+  alignment _ = alignment (undefined :: Word8)+  peek p = do+    q <- return $ castPtr p+    b <- peek q+    return (Bit b)+  poke p (Bit b) = do+    q <- return $ castPtr p+    poke q b+++instance Storable (Pixel Binary Bit) where++  sizeOf _ = sizeOf (undefined :: Bit)+  alignment _ = alignment (undefined :: Bit)+  peek p = do+    q <- return $ castPtr p+    b <- peek q+    return (PixelBinary b)+  poke p (PixelBinary b) = do+    q <- return $ castPtr p+    poke q b
src/Graphics/Image/ColorSpace/CMYK.hs view
@@ -2,10 +2,12 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Image.ColorSpace.CMYK--- Copyright   : (c) Alexey Kuleshevich 2016+-- Copyright   : (c) Alexey Kuleshevich 2017 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -17,12 +19,18 @@   ) where  import Prelude hiding (map)-import Graphics.Image.Interface+import Control.Applicative+import Data.Foldable import Data.Typeable (Typeable)-import qualified Data.Monoid as M (mappend)-import qualified Data.Colour as C-import qualified Data.Colour.Names as C+import Foreign.Ptr+import Foreign.Storable +import Graphics.Image.Interface++------------+--- CMYK ---+------------+ -- | Cyan, Magenta, Yellow and Black color space. data CMYK = CyanCMYK -- ^ Cyan           | MagCMYK  -- ^ Magenta@@ -30,6 +38,141 @@           | KeyCMYK  -- ^ Key (Black)           deriving (Eq, Enum, Typeable) +instance Show CMYK where+  show CyanCMYK = "Cyan"+  show MagCMYK  = "Magenta"+  show YelCMYK  = "Yellow"+  show KeyCMYK  = "Black"+++instance Show e => Show (Pixel CMYK e) where+  show (PixelCMYK c m y k) = "<CMYK:("++show c++"|"++show m++"|"++show y++"|"++show k++")>"+++data instance Pixel CMYK e = PixelCMYK !e !e !e !e deriving Eq++instance (Elevator e, Typeable e) => ColorSpace CMYK e where+  type Components CMYK e = (e, e, e, e)+  +  fromComponents !(c, m, y, k) = PixelCMYK c m y k+  {-# INLINE fromComponents #-}+  toComponents (PixelCMYK c m y k) = (c, m, y, k)+  {-# INLINE toComponents #-}+  broadcastC !e = PixelCMYK e e e e+  {-# INLINE broadcastC #-}+  getPxC (PixelCMYK c _ _ _) CyanCMYK = c+  getPxC (PixelCMYK _ m _ _) MagCMYK  = m+  getPxC (PixelCMYK _ _ y _) YelCMYK  = y+  getPxC (PixelCMYK _ _ _ k) KeyCMYK  = k+  {-# INLINE setPxC #-}+  setPxC (PixelCMYK _ m y k) CyanCMYK c = PixelCMYK c m y k+  setPxC (PixelCMYK c _ y k) MagCMYK  m = PixelCMYK c m y k+  setPxC (PixelCMYK c m _ k) YelCMYK  y = PixelCMYK c m y k+  setPxC (PixelCMYK c m y _) KeyCMYK  k = PixelCMYK c m y k+  {-# INLINE getPxC #-}+  mapPxC f (PixelCMYK c m y k) =+    PixelCMYK (f CyanCMYK c) (f MagCMYK m) (f YelCMYK y) (f KeyCMYK k)+  {-# INLINE mapPxC #-}+  mapPx = fmap+  {-# INLINE mapPx #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-}+++instance Functor (Pixel CMYK) where+  fmap f (PixelCMYK c m y k) = PixelCMYK (f c) (f m) (f y) (f k)+  {-# INLINE fmap #-}+++instance Applicative (Pixel CMYK) where+  pure !e = PixelCMYK e e e e+  {-# INLINE pure #-}+  (PixelCMYK fc fm fy fk) <*> (PixelCMYK c m y k) = PixelCMYK (fc c) (fm m) (fy y) (fk k)+  {-# INLINE (<*>) #-}+++instance Foldable (Pixel CMYK) where+  foldr f !z (PixelCMYK c m y k) = f c (f m (f y (f k z)))+  {-# INLINE foldr #-}+++instance Num e => Num (Pixel CMYK e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  abs         = liftA abs+  {-# INLINE abs #-}+  signum      = liftA signum+  {-# INLINE signum #-}+  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-}+++instance Fractional e => Fractional (Pixel CMYK e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}+++instance Floating e => Floating (Pixel CMYK e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}+++instance Storable e => Storable (Pixel CMYK e) where++  sizeOf _ = 3 * sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    c <- peek q+    m <- peekElemOff q 1+    y <- peekElemOff q 2+    k <- peekElemOff q 3+    return (PixelCMYK c m y k)+  poke p (PixelCMYK c m y k) = do+    q <- return $ castPtr p+    poke q c+    pokeElemOff q 1 m+    pokeElemOff q 2 y+    pokeElemOff q 3 k++-------------+--- CMYKA ---+-------------+ -- | Cyan, Magenta, Yellow and Black color space with Alpha channel. data CMYKA = CyanCMYKA  -- ^ Cyan            | MagCMYKA   -- ^ Magenta@@ -40,7 +183,7 @@   -- | Conversion to `CMYK` color space.-class ColorSpace cs => ToCMYK cs where+class ColorSpace cs Double => ToCMYK cs where    -- | Convert to a `CMYK` pixel.   toPixelCMYK :: Pixel cs Double -> Pixel CMYK Double@@ -53,8 +196,9 @@   {-# INLINE toImageCMYK #-}  + -- | Conversion to `CMYKA` from another color space with Alpha channel.-class (ToCMYK (Opaque cs), Alpha cs) => ToCMYKA cs where+class (ToCMYK (Opaque cs), AlphaSpace cs Double) => ToCMYKA cs where    -- | Convert to a `CMYKA` pixel.   toPixelCMYKA :: Pixel cs Double -> Pixel CMYKA Double@@ -68,85 +212,55 @@   toImageCMYKA = map toPixelCMYKA   {-# INLINE toImageCMYKA #-} -  -instance ColorSpace CMYK where-  type PixelElt CMYK e = (e, e, e, e)-  data Pixel CMYK e = PixelCMYK !e !e !e !e deriving Eq+data instance Pixel CMYKA e = PixelCMYKA !e !e !e !e !e deriving Eq -  fromChannel !e = PixelCMYK e e e e-  {-# INLINE fromChannel #-} -  fromElt !(c, m, y, k) = PixelCMYK c m y k-  {-# INLINE fromElt #-}--  toElt (PixelCMYK c m y k) = (c, m, y, k)-  {-# INLINE toElt #-}--  getPxCh (PixelCMYK c _ _ _) CyanCMYK = c-  getPxCh (PixelCMYK _ m _ _) MagCMYK  = m-  getPxCh (PixelCMYK _ _ y _) YelCMYK  = y-  getPxCh (PixelCMYK _ _ _ k) KeyCMYK  = k-  {-# INLINE getPxCh #-}-  -  chOp !f (PixelCMYK c m y k) =-    PixelCMYK (f CyanCMYK c) (f MagCMYK m) (f YelCMYK y) (f KeyCMYK k)-  {-# INLINE chOp #-}--  pxOp !f (PixelCMYK c m y k) = PixelCMYK (f c) (f m) (f y) (f k)-  {-# INLINE pxOp #-}--  chApp (PixelCMYK fc fm fy fk) (PixelCMYK c m y k) = PixelCMYK (fc c) (fm m) (fy y) (fk k)-  {-# INLINE chApp #-}--  pxFoldMap f (PixelCMYK c m y k) = f c `M.mappend` f m `M.mappend` f y `M.mappend` f k-  {-# INLINE pxFoldMap #-}+instance Show CMYKA where+  show CyanCMYKA  = "Cyan"+  show MagCMYKA   = "Magenta"+  show YelCMYKA   = "Yellow"+  show KeyCMYKA   = "Black"+  show AlphaCMYKA = "Alpha"+  -  csColour CyanCMYK = C.opaque C.cyan-  csColour MagCMYK  = C.opaque C.magenta-  csColour YelCMYK  = C.opaque C.yellow-  csColour KeyCMYK  = C.opaque C.black+instance Show e => Show (Pixel CMYKA e) where+  show (PixelCMYKA c m y k a) =+    "<CMYKA:("++show c++"|"++show m++"|"++show y++"|"++show k++"|"++show a++")>"  -instance ColorSpace CMYKA where-  type PixelElt CMYKA e = (e, e, e, e, e)-  data Pixel CMYKA e = PixelCMYKA !e !e !e !e !e deriving Eq--  fromChannel !e = PixelCMYKA e e e e e-  {-# INLINE fromChannel #-}--  fromElt (c, m, y, k, a) = PixelCMYKA c m y k a-  {-# INLINE fromElt #-}--  toElt (PixelCMYKA c m y k a) = (c, m, y, k, a)-  {-# INLINE toElt #-}--  getPxCh (PixelCMYKA c _ _ _ _) CyanCMYKA  = c-  getPxCh (PixelCMYKA _ m _ _ _) MagCMYKA   = m-  getPxCh (PixelCMYKA _ _ y _ _) YelCMYKA   = y-  getPxCh (PixelCMYKA _ _ _ k _) KeyCMYKA   = k-  getPxCh (PixelCMYKA _ _ _ _ a) AlphaCMYKA = a-  {-# INLINE getPxCh #-}+instance (Elevator e, Typeable e) => ColorSpace CMYKA e where+  type Components CMYKA e = (e, e, e, e, e)   -  chOp !f (PixelCMYKA c m y k a) =+  fromComponents !(c, m, y, k, a) = PixelCMYKA c m y k a+  {-# INLINE fromComponents #-}+  toComponents (PixelCMYKA c m y k a) = (c, m, y, k, a)+  {-# INLINE toComponents #-}+  broadcastC !e = PixelCMYKA e e e e e+  {-# INLINE broadcastC #-}+  getPxC (PixelCMYKA c _ _ _ _) CyanCMYKA  = c+  getPxC (PixelCMYKA _ m _ _ _) MagCMYKA   = m+  getPxC (PixelCMYKA _ _ y _ _) YelCMYKA   = y+  getPxC (PixelCMYKA _ _ _ k _) KeyCMYKA   = k+  getPxC (PixelCMYKA _ _ _ _ a) AlphaCMYKA = a+  {-# INLINE getPxC #-}+  setPxC (PixelCMYKA _ m y k a) CyanCMYKA  c = PixelCMYKA c m y k a+  setPxC (PixelCMYKA c _ y k a) MagCMYKA   m = PixelCMYKA c m y k a+  setPxC (PixelCMYKA c m _ k a) YelCMYKA   y = PixelCMYKA c m y k a+  setPxC (PixelCMYKA c m y _ a) KeyCMYKA   k = PixelCMYKA c m y k a+  setPxC (PixelCMYKA c m y k _) AlphaCMYKA a = PixelCMYKA c m y k a+  {-# INLINE setPxC #-}+  mapPxC f (PixelCMYKA c m y k a) =     PixelCMYKA (f CyanCMYKA c) (f MagCMYKA m) (f YelCMYKA y) (f KeyCMYKA k) (f AlphaCMYKA a)-  {-# INLINE chOp #-}--  pxOp !f (PixelCMYKA c m y k a) = PixelCMYKA (f c) (f m) (f y) (f k) (f a)-  {-# INLINE pxOp #-}--  chApp (PixelCMYKA fc fm fy fk fa) (PixelCMYKA c m y k a) =-    PixelCMYKA (fc c) (fm m) (fy y) (fk k) (fa a)-  {-# INLINE chApp #-}--  pxFoldMap f (PixelCMYKA c m y k a) =-    f c `M.mappend` f m `M.mappend` f y `M.mappend` f k `M.mappend` f a-  {-# INLINE pxFoldMap #-}--  csColour AlphaCMYKA = C.opaque C.grey-  csColour ch         = csColour $ opaque ch+  {-# INLINE mapPxC #-}+  mapPx = fmap+  {-# INLINE mapPx #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-}  -instance Alpha CMYKA where+instance (Elevator e, Typeable e) => AlphaSpace CMYKA e where   type Opaque CMYKA = CMYK    getAlpha (PixelCMYKA _ _ _ _ a) = a@@ -158,32 +272,94 @@   dropAlpha (PixelCMYKA c m y k _) = PixelCMYK c m y k   {-# INLINE dropAlpha #-} -  opaque CyanCMYKA  = CyanCMYK-  opaque MagCMYKA   = MagCMYK-  opaque YelCMYKA   = YelCMYK-  opaque KeyCMYKA   = KeyCMYK-  opaque AlphaCMYKA = error "Data.Image.ColorSpace.CMYK (Alpha.opaque)"-   -instance Show CMYK where-  show CyanCMYK = "Cyan"-  show MagCMYK  = "Magenta"-  show YelCMYK  = "Yellow"-  show KeyCMYK  = "Black"+instance Functor (Pixel CMYKA) where+  fmap f (PixelCMYKA c m y k a) = PixelCMYKA (f c) (f m) (f y) (f k) (f a)+  {-# INLINE fmap #-}  -instance Show CMYKA where-  show AlphaCMYKA = "Alpha"-  show ch         = show $ opaque ch+instance Applicative (Pixel CMYKA) where+  pure !e = PixelCMYKA e e e e e+  {-# INLINE pure #-}+  (PixelCMYKA fc fm fy fk fa) <*> (PixelCMYKA c m y k a) =+    PixelCMYKA (fc c) (fm m) (fy y) (fk k) (fa a)+  {-# INLINE (<*>) #-} -  -instance Show e => Show (Pixel CMYK e) where-  show (PixelCMYK c m y k) = "<CMYK:("++show c++"|"++show m++"|"++show y++"|"++show k++")>" +instance Foldable (Pixel CMYKA) where+  foldr f !z (PixelCMYKA c m y k a) = f c (f m (f y (f k (f a z))))+  {-# INLINE foldr #-} -instance Show e => Show (Pixel CMYKA e) where-  show (PixelCMYKA c m y k a) =-    "<CMYKA:("++show c++"|"++show m++"|"++show y++"|"++show k++"|"++show a++")>" +instance Num e => Num (Pixel CMYKA e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  abs         = liftA abs+  {-# INLINE abs #-}+  signum      = liftA signum+  {-# INLINE signum #-}+  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-}  +instance Fractional e => Fractional (Pixel CMYKA e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}+++instance Floating e => Floating (Pixel CMYKA e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}+++instance Storable e => Storable (Pixel CMYKA e) where++  sizeOf _ = 3 * sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    c <- peek q+    m <- peekElemOff q 1+    y <- peekElemOff q 2+    k <- peekElemOff q 3+    a <- peekElemOff q 4+    return (PixelCMYKA c m y k a)+  poke p (PixelCMYKA c m y k a) = do+    q <- return $ castPtr p+    poke q c+    pokeElemOff q 1 m+    pokeElemOff q 2 y+    pokeElemOff q 3 k+    pokeElemOff q 4 a
src/Graphics/Image/ColorSpace/Complex.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-} #if __GLASGOW_HASKELL__ >= 800   {-# OPTIONS_GHC -Wno-redundant-constraints #-} #endif@@ -20,7 +21,7 @@   conjugate   ) where -import Graphics.Image.Interface (ColorSpace(..))+import Graphics.Image.Interface (Pixel) import Control.Applicative import Data.Complex (Complex(..)) import qualified Data.Complex as C hiding (Complex(..))@@ -33,50 +34,51 @@ -- -- @ PixelRGB 4 8 6 '+:' PixelRGB 7 1 1 __==__ PixelRGB (4 ':+' 7) (8 ':+' 1) (6 ':+' 1) @ ---(+:) :: ColorSpace cs => Pixel cs e -> Pixel cs e -> Pixel cs (Complex e)+(+:) :: Applicative (Pixel cs) => Pixel cs e -> Pixel cs e -> Pixel cs (Complex e) (+:) = liftA2 (:+) {-# INLINE (+:) #-}  -- | Extracts the real part of a complex pixel.-realPart :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs e+realPart :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs e realPart = liftA C.realPart {-# INLINE realPart #-}  -- | Extracts the imaginary part of a complex pixel.-imagPart :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs e+imagPart :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs e imagPart = liftA C.imagPart {-# INLINE imagPart #-}  -- | Form a complex pixel from polar components of magnitude and phase.-mkPolar :: (ColorSpace cs, RealFloat e) => Pixel cs e -> Pixel cs e -> Pixel cs (Complex e)+mkPolar :: (Applicative (Pixel cs), RealFloat e) =>+           Pixel cs e -> Pixel cs e -> Pixel cs (Complex e) mkPolar = liftA2 C.mkPolar {-# INLINE mkPolar #-}  -- | @'cis' t@ is a complex pixel with magnitude 1 and phase t (modulo @2*'pi'@).-cis :: (ColorSpace cs, RealFloat e) => Pixel cs e -> Pixel cs (Complex e)+cis :: (Applicative (Pixel cs), RealFloat e) => Pixel cs e -> Pixel cs (Complex e) cis = liftA C.cis {-# INLINE cis #-}  -- | The function @'polar'@ takes a complex pixel and returns a (magnitude, phase) -- pair of pixels in canonical form: the magnitude is nonnegative, and the phase -- in the range @(-'pi', 'pi']@; if the magnitude is zero, then so is the phase.-polar :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> (Pixel cs e, Pixel cs e)+polar :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> (Pixel cs e, Pixel cs e) polar !zPx = (magnitude zPx, phase zPx) {-# INLINE polar #-}  -- | The nonnegative magnitude of a complex pixel.-magnitude :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs e+magnitude :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs e magnitude = liftA C.magnitude {-# INLINE magnitude #-}  -- | The phase of a complex pixel, in the range @(-'pi', 'pi']@. If the -- magnitude is zero, then so is the phase.-phase :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs e+phase :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs e phase = liftA C.phase {-# INLINE phase #-}  -- | The conjugate of a complex pixel.-conjugate :: (ColorSpace cs, RealFloat e) => Pixel cs (Complex e) -> Pixel cs (Complex e)+conjugate :: (Applicative (Pixel cs), RealFloat e) => Pixel cs (Complex e) -> Pixel cs (Complex e) conjugate = liftA C.conjugate {-# INLINE conjugate #-} 
src/Graphics/Image/ColorSpace/Gray.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- |@@ -16,22 +17,149 @@   Gray(..), Pixel(..), toGrayImages, fromGrayImages   ) where -import Prelude hiding (map, zipWith)-import qualified Prelude as P (map)-import Graphics.Image.Interface+import Prelude as P+import Control.Applicative+import Data.Foldable import Data.Typeable (Typeable)-import qualified Data.Monoid as M (mappend, mempty)-import qualified Data.Colour as C-import qualified Data.Colour.Names as C+import Foreign.Ptr+import Foreign.Storable --- ^ This is a signgle channel colorspace, that is designed to hold any channel--- from any other colorspace, hence it is not convertible to and from, but--- rather is here to allow separation of channels from other multichannel--- colorspaces. If you are looking for a true grayscale colorspace+import Graphics.Image.Interface as I++-- ^ This is a single channel colorspace, that is designed to separate Gray+-- level values from other types of colorspace, hence it is not convertible to+-- or from, but rather is here to allow operation on arbirtary single channel+-- images. If you are looking for a true grayscale colorspace -- 'Graphics.Image.ColorSpace.Luma.Y' should be used instead. data Gray = Gray deriving (Eq, Enum, Show, Typeable)  +data instance Pixel Gray e = PixelGray !e deriving (Ord, Eq)+++instance Show e => Show (Pixel Gray e) where+  show (PixelGray g) = "<Gray:("++show g++")>"+++instance (Elevator e, Typeable e) => ColorSpace Gray e where+  type Components Gray e = e++  broadcastC = PixelGray+  {-# INLINE broadcastC #-}+  fromComponents = PixelGray+  {-# INLINE fromComponents #-}+  toComponents (PixelGray g) = g+  {-# INLINE toComponents #-}+  getPxC (PixelGray g) Gray = g+  {-# INLINE getPxC #-}+  setPxC (PixelGray _) Gray g = PixelGray g+  {-# INLINE setPxC #-}+  mapPxC f (PixelGray g) = PixelGray (f Gray g)+  {-# INLINE mapPxC #-}+  mapPx = fmap+  {-# INLINE mapPx #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-}+++instance Functor (Pixel Gray) where+  fmap f (PixelGray g) = PixelGray (f g)+  {-# INLINE fmap #-}+++instance Applicative (Pixel Gray) where+  pure = PixelGray+  {-# INLINE pure #-}+  (PixelGray fg) <*> (PixelGray g) = PixelGray (fg g)+  {-# INLINE (<*>) #-}+++instance Foldable (Pixel Gray) where+  foldr f !z (PixelGray g) = f g z+  {-# INLINE foldr #-}+++instance Monad (Pixel Gray) where++  return = PixelGray+  {-# INLINE return #-}++  (>>=) (PixelGray g) f = f g+  {-# INLINE (>>=) #-}+++instance Num e => Num (Pixel Gray e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  +  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  +  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  +  abs         = liftA abs+  {-# INLINE abs #-}+  +  signum      = liftA signum+  {-# INLINE signum #-}+  +  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-}+++instance Fractional e => Fractional (Pixel Gray e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}+++instance Floating e => Floating (Pixel Gray e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}+++instance Storable e => Storable (Pixel Gray e) where++  sizeOf _ = sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    g <- peek q+    return (PixelGray g)+  poke p (PixelGray g) = do+    q <- return $ castPtr p+    poke q g+ -- | Separate an image into a list of images with 'Gray' pixels containing every -- channel from the source image. --@@ -45,7 +173,7 @@ -- toGrayImages :: (Array arr cs e, Array arr Gray e) => Image arr cs e -> [Image arr Gray e] toGrayImages !img = P.map getCh (enumFrom (toEnum 0)) where-  getCh !ch = map (PixelGray . (`getPxCh` ch)) img+  getCh !ch = I.map (PixelGray . (`getPxC` ch)) img   {-# INLINE getCh #-} {-# INLINE toGrayImages #-} @@ -61,61 +189,17 @@ -- -- It is worth noting though, despite that separating image channels can be sometimes -- pretty useful, the same effect as above can be achieved in a much simpler and--- more efficient way:+-- a more efficient way: -- -- @ map (\(PixelRGB r g b) -> PixelRGB r b g) frog @ -- fromGrayImages :: forall arr cs e . (Array arr Gray e, Array arr cs e) =>                   [Image arr Gray e] -> [cs] -> Image arr cs e-fromGrayImages = fromGrays (singleton (fromChannel 0)) where-  updateCh ch px (PixelGray e) = chOp (\ !ch' !e' -> if ch' == ch then e else e') px+fromGrayImages = fromGrays 0 where+  updateCh ch px (PixelGray e) = setPxC px ch e   {-# INLINE updateCh #-}   fromGrays img []     _      = img   fromGrays img _      []     = img-  fromGrays img (i:is) (c:cs) = fromGrays (zipWith (updateCh c) img i) is cs+  fromGrays img (i:is) (c:cs) = fromGrays (I.zipWith (updateCh c) img i) is cs   {-# INLINE fromGrays #-} {-# INLINE fromGrayImages #-}---instance ColorSpace Gray where-  type PixelElt Gray e = e-  data Pixel Gray e = PixelGray !e deriving (Ord, Eq)--  fromChannel = PixelGray-  {-# INLINE fromChannel #-}--  fromElt = PixelGray-  {-# INLINE fromElt #-}--  toElt (PixelGray g) = g-  {-# INLINE toElt #-}--  getPxCh (PixelGray g) _ = g-  {-# INLINE getPxCh #-}-  -  chOp !f (PixelGray g) = PixelGray (f Gray g)-  {-# INLINE chOp #-}-  -  pxOp !f (PixelGray g) = PixelGray (f g)-  {-# INLINE pxOp #-}--  chApp (PixelGray f) (PixelGray g) = PixelGray (f g)-  {-# INLINE chApp #-}--  pxFoldMap f (PixelGray g) = f g `M.mappend` M.mempty-  {-# INLINE pxFoldMap #-}--  csColour _ = C.opaque C.gray--  -instance Show e => Show (Pixel Gray e) where-  show (PixelGray g) = "<Gray:("++show g++")>"---instance Monad (Pixel Gray) where--  return = PixelGray-  {-# INLINE return #-}--  (>>=) (PixelGray g) f = f g-  {-# INLINE (>>=) #-}
src/Graphics/Image/ColorSpace/HSI.hs view
@@ -2,10 +2,12 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Image.ColorSpace.HSI--- Copyright   : (c) Alexey Kuleshevich 2016+-- Copyright   : (c) Alexey Kuleshevich 2017 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -17,18 +19,152 @@   ) where  import Prelude hiding (map)-import Graphics.Image.Interface+import Control.Applicative+import Data.Foldable import Data.Typeable (Typeable)-import qualified Data.Monoid as M (mappend)-import qualified Data.Colour as C-import qualified Data.Colour.Names as C+import Foreign.Ptr+import Foreign.Storable +import Graphics.Image.Interface++-----------+--- HSI ---+-----------+ -- | Hue, Saturation and Intensity color space. data HSI = HueHSI -- ^ Hue          | SatHSI -- ^ Saturation           | IntHSI -- ^ Intensity          deriving (Eq, Enum, Typeable) +data instance Pixel HSI e = PixelHSI !e !e !e deriving Eq+++instance Show HSI where+  show HueHSI = "Hue"+  show SatHSI = "Saturation"+  show IntHSI = "Intensity"+  +instance Show e => Show (Pixel HSI e) where+  show (PixelHSI h s i) = "<HSI:("++show h++"|"++show s++"|"++show i++")>"+++instance (Elevator e, Typeable e) => ColorSpace HSI e where+  type Components HSI e = (e, e, e)++  toComponents (PixelHSI h s i) = (h, s, i)+  {-# INLINE toComponents #-}+  fromComponents !(h, s, i) = PixelHSI h s i+  {-# INLINE fromComponents #-}+  broadcastC = pure+  {-# INLINE broadcastC #-}+  getPxC (PixelHSI h _ _) HueHSI = h+  getPxC (PixelHSI _ s _) SatHSI = s+  getPxC (PixelHSI _ _ i) IntHSI = i+  {-# INLINE getPxC #-}+  setPxC (PixelHSI _ s i) HueHSI h = PixelHSI h s i+  setPxC (PixelHSI h _ i) SatHSI s = PixelHSI h s i+  setPxC (PixelHSI h s _) IntHSI i = PixelHSI h s i+  {-# INLINE setPxC #-}+  mapPxC f (PixelHSI h s i) = PixelHSI (f HueHSI h) (f SatHSI s) (f IntHSI i)+  {-# INLINE mapPxC #-}+  mapPx = fmap+  {-# INLINE mapPx #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-}+++instance Functor (Pixel HSI) where+  fmap f (PixelHSI h s i) = PixelHSI (f h) (f s) (f i)+  {-# INLINE fmap #-}+++instance Applicative (Pixel HSI) where+  pure !e = PixelHSI e e e+  {-# INLINE pure #-}+  (PixelHSI fh fs fi) <*> (PixelHSI h s i) = PixelHSI (fh h) (fs s) (fi i)+  {-# INLINE (<*>) #-}+++instance Foldable (Pixel HSI) where+  foldr f !z (PixelHSI h s i) = f h (f s (f i z))+  {-# INLINE foldr #-}++instance Num e => Num (Pixel HSI e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  abs         = liftA abs+  {-# INLINE abs #-}+  signum      = liftA signum+  {-# INLINE signum #-}+  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-}+  ++instance Fractional e => Fractional (Pixel HSI e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}+++instance Floating e => Floating (Pixel HSI e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}+++instance Storable e => Storable (Pixel HSI e) where++  sizeOf _ = 3 * sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    r <- peek q+    g <- peekElemOff q 1+    b <- peekElemOff q 2+    return (PixelHSI r g b)+  poke p (PixelHSI r g b) = do+    q <- return $ castPtr p+    poke q r+    pokeElemOff q 1 g+    pokeElemOff q 2 b++------------+--- HSIA ---+------------+ -- | Hue, Saturation and Intensity color space with Alpha channel. data HSIA = HueHSIA   -- ^ Hue           | SatHSIA   -- ^ Saturation@@ -37,8 +173,11 @@           deriving (Eq, Enum, Typeable)  +data instance Pixel HSIA e = PixelHSIA !e !e !e !e deriving Eq++ -- | Conversion to `HSI` color space.-class ColorSpace cs => ToHSI cs where+class ColorSpace cs Double => ToHSI cs where    -- | Convert to an `HSI` pixel.   toPixelHSI :: Pixel cs Double -> Pixel HSI Double@@ -49,10 +188,63 @@              -> Image arr HSI Double   toImageHSI = map toPixelHSI   {-# INLINE toImageHSI #-}++++instance Show HSIA where+  show HueHSIA   = "Hue"+  show SatHSIA   = "Saturation"+  show IntHSIA   = "Intensity"+  show AlphaHSIA = "Alpha"+   +instance Show e => Show (Pixel HSIA e) where+  show (PixelHSIA h s i a) = "<HSIA:("++show h++"|"++show s++"|"++show i++"|"++show a++")>" ++instance (Elevator e, Typeable e) => ColorSpace HSIA e where+  type Components HSIA e = (e, e, e, e)++  toComponents (PixelHSIA h s i a) = (h, s, i, a)+  {-# INLINE toComponents #-}+  fromComponents !(h, s, i, a) = PixelHSIA h s i a+  {-# INLINE fromComponents #-}+  broadcastC = pure+  {-# INLINE broadcastC #-}+  getPxC (PixelHSIA h _ _ _) HueHSIA   = h+  getPxC (PixelHSIA _ s _ _) SatHSIA   = s+  getPxC (PixelHSIA _ _ i _) IntHSIA   = i+  getPxC (PixelHSIA _ _ _ a) AlphaHSIA = a+  {-# INLINE getPxC #-}+  setPxC (PixelHSIA _ s i a) HueHSIA h   = PixelHSIA h s i a+  setPxC (PixelHSIA h _ i a) SatHSIA s   = PixelHSIA h s i a+  setPxC (PixelHSIA h s _ a) IntHSIA i   = PixelHSIA h s i a+  setPxC (PixelHSIA h s i _) AlphaHSIA a = PixelHSIA h s i a+  {-# INLINE setPxC #-}+  mapPxC f (PixelHSIA h s i a) =+    PixelHSIA (f HueHSIA h) (f SatHSIA s) (f IntHSIA i) (f AlphaHSIA a)+  {-# INLINE mapPxC #-}+  mapPx = fmap+  {-# INLINE mapPx #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-}+++instance (Elevator e, Typeable e) => AlphaSpace HSIA e where+  type Opaque HSIA = HSI++  getAlpha (PixelHSIA _ _ _ a) = a+  {-# INLINE getAlpha #-}+  addAlpha !a (PixelHSI h s i) = PixelHSIA h s i a+  {-# INLINE addAlpha #-}+  dropAlpha (PixelHSIA h s i _) = PixelHSI h s i+  {-# INLINE dropAlpha #-}++ -- | Conversion to `HSIA` from another color space with Alpha channel.-class (ToHSI (Opaque cs), Alpha cs) => ToHSIA cs where+class (ToHSI (Opaque cs), AlphaSpace cs Double) => ToHSIA cs where    -- | Convert to an `HSIA` pixel.   toPixelHSIA :: Pixel cs Double -> Pixel HSIA Double@@ -66,114 +258,91 @@   toImageHSIA = map toPixelHSIA   {-# INLINE toImageHSIA #-} -  -instance ColorSpace HSI where-  type PixelElt HSI e = (e, e, e)-  data Pixel HSI e = PixelHSI !e !e !e deriving Eq -  fromChannel !e = PixelHSI e e e-  {-# INLINE fromChannel #-}+instance Functor (Pixel HSIA) where+  fmap f (PixelHSIA h s i a) = PixelHSIA (f h) (f s) (f i) (f a)+  {-# INLINE fmap #-} -  fromElt !(h, s, i) = PixelHSI h s i-  {-# INLINE fromElt #-} -  toElt (PixelHSI h s i) = (h, s, i)-  {-# INLINE toElt #-}+instance Applicative (Pixel HSIA) where+  pure !e = PixelHSIA e e e e+  {-# INLINE pure #-}+  (PixelHSIA fh fs fi fa) <*> (PixelHSIA h s i a) = PixelHSIA (fh h) (fs s) (fi i) (fa a)+  {-# INLINE (<*>) #-} -  getPxCh (PixelHSI h _ _) HueHSI   = h-  getPxCh (PixelHSI _ s _) SatHSI = s-  getPxCh (PixelHSI _ _ i) IntHSI  = i-  {-# INLINE getPxCh #-}-  -  chOp !f (PixelHSI h s i) = PixelHSI (f HueHSI h) (f SatHSI s) (f IntHSI i)-  {-# INLINE chOp #-} -  pxOp !f (PixelHSI h s i) = PixelHSI (f h) (f s) (f i)-  {-# INLINE pxOp #-}--  chApp (PixelHSI fh fs fi) (PixelHSI h s i) = PixelHSI (fh h) (fs s) (fi i)-  {-# INLINE chApp #-}--  pxFoldMap f (PixelHSI h s i) = f h `M.mappend` f s `M.mappend` f i -  {-# INLINE pxFoldMap #-}--  csColour HueHSI = C.opaque C.purple-  csColour SatHSI = C.opaque C.orange-  csColour IntHSI = C.opaque C.darkblue-+instance Foldable (Pixel HSIA) where+  foldr f !z (PixelHSIA h s i a) = f h (f s (f i (f a z)))+  {-# INLINE foldr #-}  -instance ColorSpace HSIA where-  type PixelElt HSIA e = (e, e, e, e)-  data Pixel HSIA e = PixelHSIA !e !e !e !e deriving Eq--  fromChannel !e = PixelHSIA e e e e-  {-# INLINE fromChannel #-}--  fromElt (h, s, i, a) = PixelHSIA h s i a-  {-# INLINE fromElt #-}--  toElt (PixelHSIA h s i a) = (h, s, i, a)-  {-# INLINE toElt #-}--  getPxCh (PixelHSIA r _ _ _) HueHSIA   = r-  getPxCh (PixelHSIA _ g _ _) SatHSIA = g-  getPxCh (PixelHSIA _ _ b _) IntHSIA  = b-  getPxCh (PixelHSIA _ _ _ a) AlphaHSIA = a-  {-# INLINE getPxCh #-}-  -  chOp !f (PixelHSIA h s i a) =-    PixelHSIA (f HueHSIA h) (f SatHSIA s) (f IntHSIA i) (f AlphaHSIA a)-  {-# INLINE chOp #-}--  pxOp !f (PixelHSIA h s i a) = PixelHSIA (f h) (f s) (f i) (f a)-  {-# INLINE pxOp #-}--  chApp (PixelHSIA fh fs fi fa) (PixelHSIA h s i a) = PixelHSIA (fh h) (fs s) (fi i) (fa a)-  {-# INLINE chApp #-}--  pxFoldMap f (PixelHSIA h s i a) = f h `M.mappend` f s `M.mappend` f i `M.mappend` f a-  {-# INLINE pxFoldMap #-}--  csColour AlphaHSIA = C.opaque C.gray-  csColour ch        = csColour $ opaque ch-  --instance Alpha HSIA where-  type Opaque HSIA = HSI--  getAlpha (PixelHSIA _ _ _ a) = a-  {-# INLINE getAlpha #-}-  -  addAlpha !a (PixelHSI h s i) = PixelHSIA h s i a-  {-# INLINE addAlpha #-}--  dropAlpha (PixelHSIA h s i _) = PixelHSI h s i-  {-# INLINE dropAlpha #-}--  opaque HueHSIA = HueHSI-  opaque SatHSIA = SatHSI-  opaque IntHSIA = IntHSI-  opaque _       = error "Data.Image.ColorSpace.HSI (Alpha.opaque)"+instance Num e => Num (Pixel HSIA e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  abs         = liftA abs+  {-# INLINE abs #-}+  signum      = liftA signum+  {-# INLINE signum #-}+  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-}  -instance Show HSI where-  show HueHSI = "Hue"-  show SatHSI = "Saturation"-  show IntHSI = "Intensity"-  --instance Show HSIA where-  show AlphaHSIA = "Alpha"-  show ch        = show $ opaque ch--  -instance Show e => Show (Pixel HSI e) where-  show (PixelHSI h s i) = "<HSI:("++show h++"|"++show s++"|"++show i++")>"+instance Fractional e => Fractional (Pixel HSIA e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}  -instance Show e => Show (Pixel HSIA e) where-  show (PixelHSIA h s i a) = "<HSIA:("++show h++"|"++show s++"|"++show i++"|"++show a++")>"+instance Floating e => Floating (Pixel HSIA e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}  +instance Storable e => Storable (Pixel HSIA e) where +  sizeOf _ = 3 * sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    h <- peek q+    s <- peekElemOff q 1+    i <- peekElemOff q 2+    a <- peekElemOff q 3+    return (PixelHSIA h s i a)+  poke p (PixelHSIA h s i a) = do+    q <- return $ castPtr p+    poke q h+    pokeElemOff q 1 s+    pokeElemOff q 2 i+    pokeElemOff q 3 a
src/Graphics/Image/ColorSpace/Luma.hs view
@@ -2,6 +2,8 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Image.ColorSpace.Luma@@ -17,24 +19,26 @@   ) where  import Prelude hiding (map)-import Graphics.Image.Interface+import Control.Applicative+import Data.Foldable import Data.Typeable (Typeable)-import qualified Data.Monoid as M (mappend, mempty)-import qualified Data.Colour as C-import qualified Data.Colour.Names as C+import Foreign.Ptr+import Foreign.Storable --- | Luma or brightness, that is usually denoted as @Y'@.-data Y = Y deriving (Eq, Enum, Typeable)+import Graphics.Image.Interface +---------+--- Y ---+--------- --- | Luma with Alpha channel.-data YA = YA      -- ^ Luma-        | AlphaYA -- ^ Alpha channel-        deriving (Eq, Enum, Typeable)+-- | Luma or brightness, which is usually denoted as @Y'@.+data Y = LumaY deriving (Eq, Enum, Typeable)  +data instance Pixel Y e = PixelY !e deriving (Ord, Eq)+ -- | Conversion to Luma color space.-class ColorSpace cs => ToY cs where+class ColorSpace cs Double => ToY cs where    -- | Convert a pixel to Luma pixel.   toPixelY :: Pixel cs Double -> Pixel Y Double@@ -46,124 +50,279 @@   toImageY = map toPixelY   {-# INLINE toImageY #-} -  --- | Conversion to Luma from another color space with Alpha channel.-class (ToY (Opaque cs), Alpha cs) => ToYA cs where+instance Show Y where+  show LumaY = "Luma" -  -- | Convert a pixel to Luma pixel with Alpha.-  toPixelYA :: Pixel cs Double -> Pixel YA Double-  toPixelYA px = addAlpha (getAlpha px) (toPixelY (dropAlpha px))-  {-# INLINE toPixelYA #-}+instance Show e => Show (Pixel Y e) where+  show (PixelY g) = "<Luma:("++show g++")>" -  -- | Convert an image to Luma image with Alpha.-  toImageYA :: (Array arr cs Double, Array arr YA Double) =>-               Image arr cs Double-            -> Image arr YA Double-  toImageYA = map toPixelYA-  {-# INLINE toImageYA #-}+instance (Elevator e, Typeable e) => ColorSpace Y e where+  type Components Y e = e+  broadcastC = PixelY+  {-# INLINE broadcastC #-}+  fromComponents = PixelY+  {-# INLINE fromComponents #-}+  toComponents (PixelY y) = y+  {-# INLINE toComponents #-}+  getPxC (PixelY y) LumaY = y+  {-# INLINE getPxC #-}+  setPxC _ LumaY y = PixelY y+  {-# INLINE setPxC #-}+  mapPxC f (PixelY y) = PixelY (f LumaY y)+  {-# INLINE mapPxC #-}+  mapPx = fmap+  {-# INLINE mapPx #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-}  -instance ColorSpace Y where-  type PixelElt Y e = e-  data Pixel Y e = PixelY !e deriving (Ord, Eq)+instance Functor (Pixel Y) where+  fmap f (PixelY y) = PixelY (f y)+  {-# INLINE fmap #-} -  fromChannel = PixelY-  {-# INLINE fromChannel #-} -  fromElt = PixelY-  {-# INLINE fromElt #-}+instance Applicative (Pixel Y) where+  pure = PixelY+  {-# INLINE pure #-}+  (PixelY fy) <*> (PixelY y) = PixelY (fy y)+  {-# INLINE (<*>) #-} -  toElt (PixelY y) = y-  {-# INLINE toElt #-} -  getPxCh (PixelY y) _ = y-  {-# INLINE getPxCh #-}-  -  chOp !f (PixelY y) = PixelY (f Y y)-  {-# INLINE chOp #-}- -  pxOp !f (PixelY y) = PixelY (f y)-  {-# INLINE pxOp #-}+instance Foldable (Pixel Y) where+  foldr f !z (PixelY y) = f y z+  {-# INLINE foldr #-} -  chApp (PixelY fy) (PixelY y) = PixelY (fy y)-  {-# INLINE chApp #-} -  pxFoldMap f (PixelY y) = f y `M.mappend` M.mempty-  {-# INLINE pxFoldMap #-}+instance Monad (Pixel Y) where -  csColour _ = C.opaque C.darkgray+  return = PixelY+  {-# INLINE return #-}++  (>>=) (PixelY y) f = f y+  {-# INLINE (>>=) #-}+++instance Num e => Num (Pixel Y e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  abs         = liftA abs+  {-# INLINE abs #-}+  signum      = liftA signum+  {-# INLINE signum #-}+  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-}    -instance ColorSpace YA where-  type PixelElt YA e = (e, e)-  data Pixel YA e = PixelYA !e !e deriving Eq+instance Fractional e => Fractional (Pixel Y e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-} -  fromChannel !e = PixelYA e e -  {-# INLINE fromChannel #-} -  fromElt !(g, a) = PixelYA g a-  {-# INLINE fromElt #-}+instance Floating e => Floating (Pixel Y e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-} -  toElt (PixelYA g a) = (g, a)-  {-# INLINE toElt  #-} -  getPxCh (PixelYA g _) YA      = g-  getPxCh (PixelYA _ a) AlphaYA = a-  {-# INLINE getPxCh  #-}-  -  chOp !f (PixelYA g a) = PixelYA (f YA g) (f AlphaYA a)-  {-# INLINE chOp #-}-  -  pxOp !f (PixelYA g a) = PixelYA (f g) (f a)-  {-# INLINE pxOp #-}+instance Storable e => Storable (Pixel Y e) where -  chApp (PixelYA fy fa) (PixelYA y a) = PixelYA (fy y) (fa a)-  {-# INLINE chApp #-}+  sizeOf _ = sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    y <- peek q+    return (PixelY y)+  poke p (PixelY y) = do+    q <- return $ castPtr p+    poke q y -  pxFoldMap f (PixelYA y a) = f y `M.mappend` f a-  {-# INLINE pxFoldMap #-} -  csColour AlphaYA = C.opaque C.gray-  csColour ch      = csColour $ opaque ch+++----------+--- YA ---+----------++-- | Luma with Alpha channel.+data YA = LumaYA  -- ^ Luma+        | AlphaYA -- ^ Alpha channel+        deriving (Eq, Enum, Typeable)++data instance Pixel YA e = PixelYA !e !e deriving Eq++-- | Conversion to Luma from another color space with Alpha channel.+class (ToY (Opaque cs), AlphaSpace cs Double) => ToYA cs where++  -- | Convert a pixel to Luma pixel with Alpha.+  toPixelYA :: Pixel cs Double -> Pixel YA Double+  toPixelYA px = addAlpha (getAlpha px) (toPixelY (dropAlpha px))+  {-# INLINE toPixelYA #-}++  -- | Convert an image to Luma image with Alpha.+  toImageYA :: (Array arr cs Double, Array arr YA Double) =>+               Image arr cs Double+            -> Image arr YA Double+  toImageYA = map toPixelYA+  {-# INLINE toImageYA #-}+++instance Show YA where+  show LumaYA  = "Luma"+  show AlphaYA = "Alpha"++instance (Elevator e, Typeable e) => ColorSpace YA e where+  type Components YA e = (e, e)+  broadcastC e = PixelYA e e+  {-# INLINE broadcastC #-}+  fromComponents (y, a) = PixelYA y a+  {-# INLINE fromComponents #-}+  toComponents (PixelYA y a) = (y, a)+  {-# INLINE toComponents #-}+  getPxC (PixelYA y _)  LumaYA = y+  getPxC (PixelYA _ a) AlphaYA = a+  {-# INLINE getPxC #-}+  setPxC (PixelYA _ a) LumaYA  y = PixelYA y a+  setPxC (PixelYA y _) AlphaYA a = PixelYA y a+  {-# INLINE setPxC #-}+  mapPxC f (PixelYA y a) = PixelYA (f LumaYA y) (f AlphaYA a)+  {-# INLINE mapPxC #-}+  mapPx = fmap+  {-# INLINE mapPx #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-}      -instance Alpha YA where+instance (Elevator e, Typeable e) => AlphaSpace YA e where   type Opaque YA = Y    getAlpha (PixelYA _ a) = a   {-# INLINE getAlpha  #-}-  -  addAlpha !a (PixelY g) = PixelYA g a+  addAlpha !a (PixelY y) = PixelYA y a   {-# INLINE addAlpha #-}--  dropAlpha (PixelYA g _) = PixelY g+  dropAlpha (PixelYA y _) = PixelY y   {-# INLINE dropAlpha #-} -  opaque YA = Y-  opaque _  = error "Data.Image.ColorSpace.Luma (Alpha.opaque)"+  +instance Functor (Pixel YA) where+  fmap f (PixelYA y a) = PixelYA (f y) (f a)+  {-# INLINE fmap #-}  -instance Show Y where-  show Y = "Luma"-  +instance Applicative (Pixel YA) where+  pure !e = PixelYA e e+  {-# INLINE pure #-}+  (PixelYA fy fa) <*> (PixelYA y a) = PixelYA (fy y) (fa a)+  {-# INLINE (<*>) #-} -instance Show YA where-  show AlphaYA = "Alpha"-  show ch      = show $ opaque ch++instance Foldable (Pixel YA) where+  foldr f !z (PixelYA y a) = f y (f a z)+  {-# INLINE foldr #-}+++instance Num e => Num (Pixel YA e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}   +  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  +  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  +  abs         = liftA abs+  {-# INLINE abs #-}+  +  signum      = liftA signum+  {-# INLINE signum #-}+  +  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-} -instance Show e => Show (Pixel Y e) where-  show (PixelY g) = "<Luma:("++show g++")>"+instance Fractional e => Fractional (Pixel YA e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}  -instance Show e => Show (Pixel YA e) where-  show (PixelYA g a) = "<LumaA:("++show g++"|"++show a++")>"+instance Floating e => Floating (Pixel YA e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}  -instance Monad (Pixel Y) where+instance Storable e => Storable (Pixel YA e) where -  return = PixelY-  {-# INLINE return #-}+  sizeOf _ = 2 * sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    y <- peekElemOff q 0+    a <- peekElemOff q 1+    return (PixelYA y a)+  poke p (PixelYA y a) = do+    q <- return $ castPtr p+    pokeElemOff q 0 y+    pokeElemOff q 1 a -  (>>=) (PixelY y) f = f y-  {-# INLINE (>>=) #-}
src/Graphics/Image/ColorSpace/RGB.hs view
@@ -2,42 +2,55 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Image.ColorSpace.RGB--- Copyright   : (c) Alexey Kuleshevich 2016+-- Copyright   : (c) Alexey Kuleshevich 2017 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental -- Portability : non-portable -- module Graphics.Image.ColorSpace.RGB (-  RGB(..), RGBA(..), Pixel(..), -  ToRGB(..), ToRGBA(..)+  RGB(..), RGBA(..), Pixel(..),+  ToRGB(..), ToRGBA(..),+  -- RGB16 -- Experimental     ) where  import Prelude hiding (map)-import Graphics.Image.Interface+import Control.Applicative+import Foreign.Ptr+import Foreign.Storable+import Data.Foldable import Data.Typeable (Typeable)-import qualified Data.Monoid as M (mappend)-import qualified Data.Colour as C-import qualified Data.Colour.Names as C +import Graphics.Image.Interface +-----------+--- RGB ---+-----------+ -- | Red, Green and Blue color space. data RGB = RedRGB          | GreenRGB          | BlueRGB deriving (Eq, Enum, Typeable) --- | Red, Green and Blue color space with Alpha channel.-data RGBA = RedRGBA-          | GreenRGBA-          | BlueRGBA-          | AlphaRGBA deriving (Eq, Enum, Typeable)+instance Show RGB where+  show RedRGB   = "Red"+  show GreenRGB = "Green"+  show BlueRGB  = "Blue"  +data instance Pixel RGB e = PixelRGB !e !e !e deriving Eq++instance Show e => Show (Pixel RGB e) where+  show (PixelRGB r g b) = "<RGB:("++show r++"|"++show g++"|"++show b++")>"++ -- | Conversion to `RGB` color space.-class ColorSpace cs => ToRGB cs where+class ColorSpace cs Double => ToRGB cs where    -- | Convert to an `RGB` pixel.   toPixelRGB :: Pixel cs Double -> Pixel RGB Double@@ -50,8 +63,159 @@   {-# INLINE toImageRGB #-}  ++instance (Elevator e, Typeable e) => ColorSpace RGB e where+  type Components RGB e = (e, e, e)++  toComponents (PixelRGB r g b) = (r, g, b)+  {-# INLINE toComponents #-}+  +  fromComponents !(r, g, b) = PixelRGB r g b+  {-# INLINE fromComponents #-}++  broadcastC = pure+  {-# INLINE broadcastC #-}++  getPxC (PixelRGB r _ _) RedRGB   = r+  getPxC (PixelRGB _ g _) GreenRGB = g+  getPxC (PixelRGB _ _ b) BlueRGB  = b+  {-# INLINE getPxC #-}++  setPxC (PixelRGB _ g b) RedRGB   r = PixelRGB r g b+  setPxC (PixelRGB r _ b) GreenRGB g = PixelRGB r g b+  setPxC (PixelRGB r g _) BlueRGB  b = PixelRGB r g b+  {-# INLINE setPxC #-}++  mapPxC f (PixelRGB r g b) = PixelRGB (f RedRGB r) (f GreenRGB g) (f BlueRGB b)+  {-# INLINE mapPxC #-}++  mapPx = fmap+  {-# INLINE mapPx #-}++  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}++  foldlPx = foldl'+  {-# INLINE foldlPx #-}+++++instance Functor (Pixel RGB) where+  fmap f (PixelRGB r g b) = PixelRGB (f r) (f g) (f b)+  {-# INLINE fmap #-}+++instance Applicative (Pixel RGB) where+  pure !e = PixelRGB e e e+  {-# INLINE pure #-}+  (PixelRGB fr fg fb) <*> (PixelRGB r g b) = PixelRGB (fr r) (fg g) (fb b)+  {-# INLINE (<*>) #-}+++instance Foldable (Pixel RGB) where+  foldr f !z (PixelRGB r g b) = f r (f g (f b z))+  {-# INLINE foldr #-}+++instance Num e => Num (Pixel RGB e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  abs         = liftA abs+  {-# INLINE abs #-}+  signum      = liftA signum+  {-# INLINE signum #-}+  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-}+  ++instance Fractional e => Fractional (Pixel RGB e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}+++instance Floating e => Floating (Pixel RGB e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}+++instance Storable e => Storable (Pixel RGB e) where++  sizeOf _ = 3 * sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    r <- peek q+    g <- peekElemOff q 1+    b <- peekElemOff q 2+    return (PixelRGB r g b)+  poke p (PixelRGB r g b) = do+    q <- return $ castPtr p+    poke q r+    pokeElemOff q 1 g+    pokeElemOff q 2 b+++++------------+--- RGBA ---+------------+++-- | Red, Green and Blue color space with Alpha channel.+data RGBA = RedRGBA+          | GreenRGBA+          | BlueRGBA+          | AlphaRGBA deriving (Eq, Enum, Typeable)++instance Show RGBA where+  show RedRGBA   = "Red"+  show GreenRGBA = "Green"+  show BlueRGBA  = "Blue"+  show AlphaRGBA = "Alpha"++data instance Pixel RGBA e = PixelRGBA !e !e !e !e deriving Eq+++instance Show e => Show (Pixel RGBA e) where+  show (PixelRGBA r g b a) = "<RGBA:("++show r++"|"++show g++"|"++show b++"|"++show a++")>"++ -- | Conversion to `RGBA` from another color space with Alpha channel.-class (ToRGB (Opaque cs), Alpha cs) => ToRGBA cs where+class (ToRGB (Opaque cs), AlphaSpace cs Double) => ToRGBA cs where    -- | Convert to an `RGBA` pixel.   toPixelRGBA :: Pixel cs Double -> Pixel RGBA Double@@ -65,113 +229,291 @@   toImageRGBA = map toPixelRGBA   {-# INLINE toImageRGBA #-} ++instance (Elevator e, Typeable e) => ColorSpace RGBA e where+  type Components RGBA e = (e, e, e, e)++  toComponents (PixelRGBA r g b a) = (r, g, b, a)+  {-# INLINE toComponents #-}   -instance ColorSpace RGB where-  type PixelElt RGB e = (e, e, e)-  data Pixel RGB e = PixelRGB !e !e !e deriving Eq+  fromComponents !(r, g, b, a) = PixelRGBA r g b a+  {-# INLINE fromComponents #-} -  fromChannel !e = PixelRGB e e e-  {-# INLINE fromChannel #-}+  broadcastC = pure+  {-# INLINE broadcastC #-} -  fromElt !(r, g, b) = PixelRGB r g b-  {-# INLINE fromElt #-}+  getPxC (PixelRGBA r _ _ _) RedRGBA   = r+  getPxC (PixelRGBA _ g _ _) GreenRGBA = g+  getPxC (PixelRGBA _ _ b _) BlueRGBA  = b+  getPxC (PixelRGBA _ _ _ a) AlphaRGBA = a+  {-# INLINE getPxC #-} -  toElt (PixelRGB r g b) = (r, g, b)-  {-# INLINE toElt #-}+  setPxC (PixelRGBA _ g b a) RedRGBA   r = PixelRGBA r g b a+  setPxC (PixelRGBA r _ b a) GreenRGBA g = PixelRGBA r g b a+  setPxC (PixelRGBA r g _ a) BlueRGBA  b = PixelRGBA r g b a+  setPxC (PixelRGBA r g b _) AlphaRGBA a = PixelRGBA r g b a+  {-# INLINE setPxC #-} -  getPxCh (PixelRGB r _ _) RedRGB   = r-  getPxCh (PixelRGB _ g _) GreenRGB = g-  getPxCh (PixelRGB _ _ b) BlueRGB  = b-  {-# INLINE getPxCh #-}-  -  chOp !f (PixelRGB r g b) = PixelRGB (f RedRGB r) (f GreenRGB g) (f BlueRGB b)-  {-# INLINE chOp #-}+  mapPxC f (PixelRGBA r g b a) =+    PixelRGBA (f RedRGBA r) (f GreenRGBA g) (f BlueRGBA b) (f AlphaRGBA a)+  {-# INLINE mapPxC #-} -  pxOp !f (PixelRGB r g b) = PixelRGB (f r) (f g) (f b)-  {-# INLINE pxOp #-}+  mapPx = fmap+  {-# INLINE mapPx #-} -  chApp (PixelRGB fr fg fb) (PixelRGB r g b) = PixelRGB (fr r) (fg g) (fb b)-  {-# INLINE chApp #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-} -  pxFoldMap f (PixelRGB r g b) = f r `M.mappend` f g `M.mappend` f b-  {-# INLINE pxFoldMap #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-} -  csColour RedRGB   = C.opaque C.red-  csColour GreenRGB = C.opaque C.green-  csColour BlueRGB  = C.opaque C.blue-   -instance ColorSpace RGBA where-  type PixelElt RGBA e = (e, e, e, e)-  data Pixel RGBA e = PixelRGBA !e !e !e !e deriving Eq+instance (Elevator e, Typeable e) => AlphaSpace RGBA e where+  type Opaque RGBA = RGB -  fromChannel !e = PixelRGBA e e e e-  {-# INLINE fromChannel #-}+  getAlpha (PixelRGBA _ _ _ a) = a+  {-# INLINE getAlpha #-}+  addAlpha !a (PixelRGB r g b) = PixelRGBA r g b a+  {-# INLINE addAlpha #-}+  dropAlpha (PixelRGBA r g b _) = PixelRGB r g b+  {-# INLINE dropAlpha #-} -  fromElt (r, g, b, a) = PixelRGBA r g b a-  {-# INLINE fromElt #-} -  toElt (PixelRGBA r g b a) = (r, g, b, a)-  {-# INLINE toElt #-} -  getPxCh (PixelRGBA r _ _ _) RedRGBA   = r-  getPxCh (PixelRGBA _ g _ _) GreenRGBA = g-  getPxCh (PixelRGBA _ _ b _) BlueRGBA  = b-  getPxCh (PixelRGBA _ _ _ a) AlphaRGBA = a-  {-# INLINE getPxCh #-}+instance Functor (Pixel RGBA) where+  fmap f (PixelRGBA r g b a) = PixelRGBA (f r) (f g) (f b) (f a)+  {-# INLINE fmap #-}++instance Applicative (Pixel RGBA) where+  pure !e = PixelRGBA e e e e+  {-# INLINE pure #-}+  (PixelRGBA fr fg fb fa) <*> (PixelRGBA r g b a) = PixelRGBA (fr r) (fg g) (fb b) (fa a)+  {-# INLINE (<*>) #-}++instance Foldable (Pixel RGBA) where+  foldr f !z (PixelRGBA r g b a) = f r (f g (f b (f a z)))+  {-# INLINE foldr #-}++++instance Num e => Num (Pixel RGBA e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  abs         = liftA abs+  {-# INLINE abs #-}+  signum      = liftA signum+  {-# INLINE signum #-}+  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-}+++instance Fractional e => Fractional (Pixel RGBA e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}+++instance Floating e => Floating (Pixel RGBA e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}++ +instance Storable e => Storable (Pixel RGBA e) where++  sizeOf _ = 3 * sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    r <- peek q+    g <- peekElemOff q 1+    b <- peekElemOff q 2+    a <- peekElemOff q 3+    return (PixelRGBA r g b a)+  poke p (PixelRGBA r g b a) = do+    q <- return $ castPtr p+    poke q r+    pokeElemOff q 1 g+    pokeElemOff q 2 b+    pokeElemOff q 3 a++++++------------------------------------------------++-- -- | Red, Green and Blue color space.+-- data RGB16 = RedRGB16+--           | GreenRGB16+--           | BlueRGB16 deriving (Eq, Enum, Typeable, Show)+++-- --data instance Pixel RGB16 Word16 = PixelRGB16 !Word16 !Word16 !Word16 deriving Eq+-- data instance Pixel RGB16 Word16 = PixelRGB16+--                                    {-# UNPACK #-} !Word16+--                                    {-# UNPACK #-} !Word16+--                                    {-# UNPACK #-} !Word16 deriving Eq+-- --data instance Pixel RGB16 Word16 = PixelRGB16 ++-- instance ColorSpace RGB16 Word16 where+--   type Components RGB16 Word16 = (Word16, Word16, Word16)++--   broadcastC !e = PixelRGB16 e e e+--   {-# INLINE broadcastC #-}++--   toComponents (PixelRGB16 r g b) = (r, g, b)+--   {-# INLINE toComponents #-}   -  chOp !f (PixelRGBA r g b a) =-    PixelRGBA (f RedRGBA r) (f GreenRGBA g) (f BlueRGBA b) (f AlphaRGBA a)-  {-# INLINE chOp #-}+--   fromComponents !(r, g, b) = PixelRGB16 r g b+--   {-# INLINE fromComponents #-} -  pxOp !f (PixelRGBA r g b a) = PixelRGBA (f r) (f g) (f b) (f a)-  {-# INLINE pxOp #-} -  chApp (PixelRGBA fr fg fb fa) (PixelRGBA r g b a) = PixelRGBA (fr r) (fg g) (fb b) (fa a)-  {-# INLINE chApp #-}+--   getPxC (PixelRGB16 r _ _) RedRGB16   = r+--   getPxC (PixelRGB16 _ g _) GreenRGB16 = g+--   getPxC (PixelRGB16 _ _ b) BlueRGB16  = b+--   {-# INLINE getPxC #-} -  pxFoldMap f (PixelRGBA r g b a) = f r `M.mappend` f g `M.mappend` f b `M.mappend` f a-  {-# INLINE pxFoldMap #-}+--   setPxC (PixelRGB16 _ g b) RedRGB16   r = PixelRGB16 r g b+--   setPxC (PixelRGB16 r _ b) GreenRGB16 g = PixelRGB16 r g b+--   setPxC (PixelRGB16 r g _) BlueRGB16  b = PixelRGB16 r g b+--   {-# INLINE setPxC #-} -  csColour AlphaRGBA = C.opaque C.gray-  csColour ch        = csColour $ opaque ch+--   mapPxC f (PixelRGB16 r g b) = PixelRGB16 (f RedRGB16 r) (f GreenRGB16 g) (f BlueRGB16 b)+--   {-# INLINE mapPxC #-} +--   mapPx f (PixelRGB16 r g b) = PixelRGB16 (f r) (f g) (f b)+--   {-# INLINE mapPx #-} -instance Alpha RGBA where-  type Opaque RGBA = RGB+--   zipWithPx f (PixelRGB16 r1 g1 b1) (PixelRGB16 r2 g2 b2) =+--     PixelRGB16 (f r1 r2) (f g1 g2) (f b1 b2)+--   {-# INLINE zipWithPx #-} -  getAlpha (PixelRGBA _ _ _ a) = a-  {-# INLINE getAlpha #-}+--   foldlPx f !acc (PixelRGB16 r g b) = f (f (f acc r) g) b+++-- instance Num (Pixel RGB16 Word16) where+--   (+)         = zipWithPx (+)   -  addAlpha !a (PixelRGB r g b) = PixelRGBA r g b a-  {-# INLINE addAlpha #-}+--   (-)         = zipWithPx (-)+--   {-# INLINE (-) #-}+  +--   (*)         = zipWithPx (*)+--   {-# INLINE (*) #-}+  +--   abs         = mapPx abs+--   {-# INLINE abs #-}+  +--   signum      = mapPx signum+--   {-# INLINE signum #-}+  +--   fromInteger = broadcastC . fromInteger+--   {-# INLINE fromInteger #-} -  dropAlpha (PixelRGBA r g b _) = PixelRGB r g b-  {-# INLINE dropAlpha #-} -  opaque RedRGBA   = RedRGB-  opaque GreenRGBA = GreenRGB-  opaque BlueRGBA  = BlueRGB-  opaque AlphaRGBA = error "Data.Image.ColorSpace.RGB (Alpha.opaque)"+-- -- instance Fractional (Pixel RGB16 Word16) where+-- --   (/)          = zipWithPx (/)+-- --   {-# INLINE (/) #-}+  +-- --   recip        = mapPx recip+-- --   {-# INLINE recip #-} +-- --   fromRational = broadcastC . fromRational+-- --   {-# INLINE fromRational #-} -instance Show RGB where-  show RedRGB   = "Red"-  show GreenRGB = "Green"-  show BlueRGB  = "Blue" +-- -- instance Floating (Pixel RGB16 Word16) where+-- --   pi      = broadcastC pi+-- --   {-# INLINE pi #-} -instance Show RGBA where-  show AlphaRGBA = "Alpha"-  show ch        = show $ opaque ch+-- --   exp     = mapPx exp+-- --   {-# INLINE exp #-} - -instance Show e => Show (Pixel RGB e) where-  show (PixelRGB r g b) = "<RGB:("++show r++"|"++show g++"|"++show b++")>"+-- --   log     = mapPx log+-- --   {-# INLINE log #-}+  +-- --   sin     = mapPx sin+-- --   {-# INLINE sin #-}+  +-- --   cos     = mapPx cos+-- --   {-# INLINE cos #-}+  +-- --   asin    = mapPx asin+-- --   {-# INLINE asin #-}+  +-- --   atan    = mapPx atan+-- --   {-# INLINE atan #-}+  +-- --   acos    = mapPx acos+-- --   {-# INLINE acos #-}+  +-- --   sinh    = mapPx sinh+-- --   {-# INLINE sinh #-}+  +-- --   cosh    = mapPx cosh+-- --   {-# INLINE cosh #-}+  +-- --   asinh   = mapPx asinh+-- --   {-# INLINE asinh #-}+  +-- --   atanh   = mapPx atanh+-- --   {-# INLINE atanh #-}+  +-- --   acosh   = mapPx acosh+-- --   {-# INLINE acosh #-}  -instance Show e => Show (Pixel RGBA e) where-  show (PixelRGBA r g b a) = "<RGBA:("++show r++"|"++show g++"|"++show b++"|"++show a++")>"+-- -- instance Show RGB16 where+-- --   show RedRGB16   = "Red"+-- --   show GreenRGB16 = "Green"+-- --   show BlueRGB16  = "Blue" +-- -- instance Show (Pixel RGB16 Word16) where+-- --   show (PixelRGB16 r g b) = "<RGB:("++show r++"|"++show g++"|"++show b++")>"  +-- -- instance Storable (Pixel RGB16 Word16) where++-- --   sizeOf _ = 3 * sizeOf (undefined :: Word16)+-- --   alignment _ = alignment (undefined :: Word16)+-- --   peek p = do+-- --     q <- return $ castPtr p+-- --     r <- peek q+-- --     g <- peekElemOff q 1+-- --     b <- peekElemOff q 2+-- --     return (PixelRGB16 r g b)+-- --   poke p (PixelRGB16 r g b) = do+-- --     q <- return $ castPtr p+-- --     poke q r+-- --     pokeElemOff q 1 g+-- --     pokeElemOff q 2 b
src/Graphics/Image/ColorSpace/YCbCr.hs view
@@ -2,10 +2,12 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Image.ColorSpace.YCbCr--- Copyright   : (c) Alexey Kuleshevich 2016+-- Copyright   : (c) Alexey Kuleshevich 2017 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -17,20 +19,159 @@   ) where  import Prelude hiding (map)-import Graphics.Image.Interface+import Control.Applicative+import Data.Foldable import Data.Typeable (Typeable)-import qualified Data.Monoid as M (mappend)-import qualified Data.Colour as C-import qualified Data.Colour.Names as C+import Foreign.Ptr+import Foreign.Storable +import Graphics.Image.Interface ++-------------+--- YCbCr ---+-------------++ -- | Color space is used to encode RGB information and is used in JPEG compression. data YCbCr = LumaYCbCr  -- ^ Luma component (commonly denoted as __Y'__)            | CBlueYCbCr -- ^ Blue difference chroma component            | CRedYCbCr  -- ^ Red difference chroma component            deriving (Eq, Enum, Typeable) +data instance Pixel YCbCr e = PixelYCbCr !e !e !e deriving Eq ++instance Show YCbCr where+  show LumaYCbCr  = "Luma"+  show CBlueYCbCr = "Blue Chroma"+  show CRedYCbCr  = "Red Chroma"+++instance Show e => Show (Pixel YCbCr e) where+  show (PixelYCbCr y b r) = "<YCbCr:("++show y++"|"++show b++"|"++show r++")>"+++instance (Elevator e, Typeable e) => ColorSpace YCbCr e where+  type Components YCbCr e = (e, e, e)++  broadcastC !e = PixelYCbCr e e e+  {-# INLINE broadcastC #-}+  fromComponents !(y, b, r) = PixelYCbCr y b r+  {-# INLINE fromComponents #-}+  toComponents (PixelYCbCr y b r) = (y, b, r)+  {-# INLINE toComponents #-}+  getPxC (PixelYCbCr y _ _) LumaYCbCr  = y+  getPxC (PixelYCbCr _ b _) CBlueYCbCr = b+  getPxC (PixelYCbCr _ _ r) CRedYCbCr  = r+  {-# INLINE getPxC #-}+  setPxC (PixelYCbCr _ b r) LumaYCbCr  y = PixelYCbCr y b r+  setPxC (PixelYCbCr y _ r) CBlueYCbCr b = PixelYCbCr y b r+  setPxC (PixelYCbCr y b _) CRedYCbCr  r = PixelYCbCr y b r+  {-# INLINE setPxC #-}+  mapPxC f (PixelYCbCr y b r) = PixelYCbCr (f LumaYCbCr y) (f CBlueYCbCr b) (f CRedYCbCr r)+  {-# INLINE mapPxC #-}+  mapPx = fmap+  {-# INLINE mapPx #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-}+++instance Functor (Pixel YCbCr) where+  fmap f (PixelYCbCr y b r) = PixelYCbCr (f y) (f b) (f r)+  {-# INLINE fmap #-}+++instance Applicative (Pixel YCbCr) where+  pure !e = PixelYCbCr e e e+  {-# INLINE pure #-}+  (PixelYCbCr fy fb fr) <*> (PixelYCbCr y b r) = PixelYCbCr (fy y) (fb b) (fr r)+  {-# INLINE (<*>) #-}+++instance Foldable (Pixel YCbCr) where+  foldr f !z (PixelYCbCr y b r) = f y (f b (f r z))+  {-# INLINE foldr #-}+++instance Num e => Num (Pixel YCbCr e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  abs         = liftA abs+  {-# INLINE abs #-}+  signum      = liftA signum+  {-# INLINE signum #-}+  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-}+++instance Fractional e => Fractional (Pixel YCbCr e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}+++instance Floating e => Floating (Pixel YCbCr e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}++++instance Storable e => Storable (Pixel YCbCr e) where++  sizeOf _ = 3 * sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    y <- peek q+    b <- peekElemOff q 1+    r <- peekElemOff q 2+    return (PixelYCbCr y b r)+  poke p (PixelYCbCr y b r) = do+    q <- return $ castPtr p+    pokeElemOff q 0 y+    pokeElemOff q 1 b+    pokeElemOff q 2 r+++--------------+--- YCbCrA ---+--------------++ -- | YCbCr color space with Alpha channel. data YCbCrA = LumaYCbCrA  -- ^ Luma component (commonly denoted as __Y'__)             | CBlueYCbCrA -- ^ Blue difference chroma component@@ -38,9 +179,52 @@             | AlphaYCbCrA -- ^ Alpha component.             deriving (Eq, Enum, Typeable) +data instance Pixel YCbCrA e = PixelYCbCrA !e !e !e !e deriving Eq ++instance Show YCbCrA where+  show LumaYCbCrA  = "Luma"+  show CBlueYCbCrA = "Blue Chroma"+  show CRedYCbCrA  = "Red Chroma"+  show AlphaYCbCrA = "Alpha"++ +instance Show e => Show (Pixel YCbCrA e) where+  show (PixelYCbCrA y b r a) = "<YCbCrA:("++show y++"|"++show b++"|"++show r++"|"++show a++")>"+++instance (Elevator e, Typeable e) => ColorSpace YCbCrA e where+  type Components YCbCrA e = (e, e, e, e)++  broadcastC !e = PixelYCbCrA e e e e+  {-# INLINE broadcastC #-}+  fromComponents !(y, b, r, a) = PixelYCbCrA y b r a+  {-# INLINE fromComponents #-}+  toComponents (PixelYCbCrA y b r a) = (y, b, r, a)+  {-# INLINE toComponents #-}+  getPxC (PixelYCbCrA y _ _ _) LumaYCbCrA  = y+  getPxC (PixelYCbCrA _ b _ _) CBlueYCbCrA = b+  getPxC (PixelYCbCrA _ _ r _) CRedYCbCrA  = r+  getPxC (PixelYCbCrA _ _ _ a) AlphaYCbCrA = a+  {-# INLINE getPxC #-}+  setPxC (PixelYCbCrA _ b r a) LumaYCbCrA  y = PixelYCbCrA y b r a+  setPxC (PixelYCbCrA y _ r a) CBlueYCbCrA b = PixelYCbCrA y b r a+  setPxC (PixelYCbCrA y b _ a) CRedYCbCrA  r = PixelYCbCrA y b r a+  setPxC (PixelYCbCrA y b r _) AlphaYCbCrA a = PixelYCbCrA y b r a+  {-# INLINE setPxC #-}+  mapPxC f (PixelYCbCrA y b r a) =+    PixelYCbCrA (f LumaYCbCrA y) (f CBlueYCbCrA b) (f CRedYCbCrA r) (f AlphaYCbCrA a)+  {-# INLINE mapPxC #-}+  mapPx = fmap+  {-# INLINE mapPx #-}+  zipWithPx = liftA2+  {-# INLINE zipWithPx #-}+  foldlPx = foldl'+  {-# INLINE foldlPx #-}++   -- | Conversion to `YCbCr` color space.-class ColorSpace cs => ToYCbCr cs where+class ColorSpace cs Double => ToYCbCr cs where    -- | Convert to an `YCbCr` pixel.   toPixelYCbCr :: Pixel cs Double -> Pixel YCbCr Double@@ -54,7 +238,7 @@   -- | Conversion to `YCbCrA` from another color space with Alpha channel.-class (ToYCbCr (Opaque cs), Alpha cs) => ToYCbCrA cs where+class (ToYCbCr (Opaque cs), AlphaSpace cs Double) => ToYCbCrA cs where    -- | Convert to an `YCbCrA` pixel.   toPixelYCbCrA :: Pixel cs Double -> Pixel YCbCrA Double@@ -69,112 +253,104 @@   {-# INLINE toImageYCbCrA #-}    -instance ColorSpace YCbCr where-  type PixelElt YCbCr e = (e, e, e)-  data Pixel YCbCr e = PixelYCbCr !e !e !e deriving Eq -  fromChannel !e = PixelYCbCr e e e-  {-# INLINE fromChannel #-}--  fromElt !(y, b, r) = PixelYCbCr y b r-  {-# INLINE fromElt #-}--  toElt (PixelYCbCr y b r) = (y, b, r)-  {-# INLINE toElt #-}--  getPxCh (PixelYCbCr y _ _) LumaYCbCr  = y-  getPxCh (PixelYCbCr _ b _) CBlueYCbCr = b-  getPxCh (PixelYCbCr _ _ r) CRedYCbCr  = r-  {-# INLINE getPxCh #-}-  -  chOp !f (PixelYCbCr y b r) = PixelYCbCr (f LumaYCbCr y) (f CBlueYCbCr b) (f CRedYCbCr r)-  {-# INLINE chOp #-}--  pxOp !f (PixelYCbCr y b r) = PixelYCbCr (f y) (f b) (f r)-  {-# INLINE pxOp #-}--  chApp (PixelYCbCr fy fb fr) (PixelYCbCr y b r) = PixelYCbCr (fy y) (fb b) (fr r)-  {-# INLINE chApp #-}--  pxFoldMap f (PixelYCbCr y b r) = f y `M.mappend` f b `M.mappend` f r-  {-# INLINE pxFoldMap #-}--  csColour LumaYCbCr  = C.opaque C.darkgray-  csColour CBlueYCbCr = C.opaque C.darkblue-  csColour CRedYCbCr  = C.opaque C.darkred-  --instance ColorSpace YCbCrA where-  type PixelElt YCbCrA e = (e, e, e, e)-  data Pixel YCbCrA e = PixelYCbCrA !e !e !e !e deriving Eq--  fromChannel !e = PixelYCbCrA e e e e-  {-# INLINE fromChannel #-}--  fromElt (y, b, r, a) = PixelYCbCrA y b r a-  {-# INLINE fromElt #-}--  toElt (PixelYCbCrA y b r a) = (y, b, r, a)-  {-# INLINE toElt #-}--  getPxCh (PixelYCbCrA y _ _ _) LumaYCbCrA  = y-  getPxCh (PixelYCbCrA _ b _ _) CBlueYCbCrA = b-  getPxCh (PixelYCbCrA _ _ r _) CRedYCbCrA  = r-  getPxCh (PixelYCbCrA _ _ _ a) AlphaYCbCrA = a-  {-# INLINE getPxCh #-}-  -  chOp !f (PixelYCbCrA y b r a) =-    PixelYCbCrA (f LumaYCbCrA y) (f CBlueYCbCrA b) (f CRedYCbCrA r) (f AlphaYCbCrA a)-  {-# INLINE chOp #-}--  pxOp !f (PixelYCbCrA y b r a) = PixelYCbCrA (f y) (f b) (f r) (f a)-  {-# INLINE pxOp #-}--  chApp (PixelYCbCrA fy fb fr fa) (PixelYCbCrA y b r a) = PixelYCbCrA (fy y) (fb b) (fr r) (fa a)-  {-# INLINE chApp #-}--  pxFoldMap f (PixelYCbCrA y b r a) = f y `M.mappend` f b `M.mappend` f r `M.mappend` f a-  {-# INLINE pxFoldMap #-}--  csColour AlphaYCbCrA = C.opaque C.gray-  csColour ch          = csColour $ opaque ch---instance Alpha YCbCrA where+instance (Elevator e, Typeable e) => AlphaSpace YCbCrA e where   type Opaque YCbCrA = YCbCr    getAlpha (PixelYCbCrA _ _ _ a) = a   {-# INLINE getAlpha #-}-     addAlpha !a (PixelYCbCr y b r) = PixelYCbCrA y b r a   {-# INLINE addAlpha #-}-   dropAlpha (PixelYCbCrA y b r _) = PixelYCbCr y b r   {-# INLINE dropAlpha #-} -  opaque LumaYCbCrA  = LumaYCbCr-  opaque CBlueYCbCrA = CBlueYCbCr-  opaque CRedYCbCrA  = CRedYCbCr-  opaque AlphaYCbCrA = error "Data.Image.ColorSpace.YCbCr (Alpha.opaque)" +instance Functor (Pixel YCbCrA) where+  fmap f (PixelYCbCrA y b r a) = PixelYCbCrA (f y) (f b) (f r) (f a)+  {-# INLINE fmap #-} -instance Show YCbCr where-  show LumaYCbCr  = "Luma"-  show CBlueYCbCr = "Blue Chroma"-  show CRedYCbCr  = "Red Chroma" +instance Applicative (Pixel YCbCrA) where+  pure !e = PixelYCbCrA e e e e+  {-# INLINE pure #-}+  (PixelYCbCrA fy fb fr fa) <*> (PixelYCbCrA y b r a) = PixelYCbCrA (fy y) (fb b) (fr r) (fa a)+  {-# INLINE (<*>) #-} -instance Show YCbCrA where-  show AlphaYCbCrA = "Alpha"-  show ch          = show $ opaque ch - -instance Show e => Show (Pixel YCbCr e) where-  show (PixelYCbCr y b r) = "<YCbCr:("++show y++"|"++show b++"|"++show r++")>"+instance Foldable (Pixel YCbCrA) where+  foldr f !z (PixelYCbCrA y b r a) = f y (f b (f r (f a z)))+  {-# INLINE foldr #-}  -instance Show e => Show (Pixel YCbCrA e) where-  show (PixelYCbCrA y b r a) = "<YCbCrA:("++show y++"|"++show b++"|"++show r++"|"++show a++")>"+instance Num e => Num (Pixel YCbCrA e) where+  (+)         = liftA2 (+)+  {-# INLINE (+) #-}+  (-)         = liftA2 (-)+  {-# INLINE (-) #-}+  (*)         = liftA2 (*)+  {-# INLINE (*) #-}+  abs         = liftA abs+  {-# INLINE abs #-}+  signum      = liftA signum+  {-# INLINE signum #-}+  fromInteger = pure . fromInteger+  {-# INLINE fromInteger #-} ++instance Fractional e => Fractional (Pixel YCbCrA e) where+  (/)          = liftA2 (/)+  {-# INLINE (/) #-}+  recip        = liftA recip+  {-# INLINE recip #-}+  fromRational = pure . fromRational+  {-# INLINE fromRational #-}+++instance Floating e => Floating (Pixel YCbCrA e) where+  pi      = pure pi+  {-# INLINE pi #-}+  exp     = liftA exp+  {-# INLINE exp #-}+  log     = liftA log+  {-# INLINE log #-}+  sin     = liftA sin+  {-# INLINE sin #-}+  cos     = liftA cos+  {-# INLINE cos #-}+  asin    = liftA asin+  {-# INLINE asin #-}+  atan    = liftA atan+  {-# INLINE atan #-}+  acos    = liftA acos+  {-# INLINE acos #-}+  sinh    = liftA sinh+  {-# INLINE sinh #-}+  cosh    = liftA cosh+  {-# INLINE cosh #-}+  asinh   = liftA asinh+  {-# INLINE asinh #-}+  atanh   = liftA atanh+  {-# INLINE atanh #-}+  acosh   = liftA acosh+  {-# INLINE acosh #-}+++instance Storable e => Storable (Pixel YCbCrA e) where++  sizeOf _ = 3 * sizeOf (undefined :: e)+  alignment _ = alignment (undefined :: e)+  peek p = do+    q <- return $ castPtr p+    y <- peekElemOff q 0+    b <- peekElemOff q 1+    r <- peekElemOff q 2+    a <- peekElemOff q 3+    return (PixelYCbCrA y b r a)+  poke p (PixelYCbCrA y b r a) = do+    q <- return $ castPtr p+    poke q y+    pokeElemOff q 1 b+    pokeElemOff q 2 r+    pokeElemOff q 3 a  
src/Graphics/Image/IO.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE FlexibleContexts #-} -- | -- Module      : Graphics.Image.IO--- Copyright   : (c) Alexey Kuleshevich 2016+-- Copyright   : (c) Alexey Kuleshevich 2017 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -41,10 +41,6 @@ import Data.Maybe (fromMaybe)  import qualified Data.ByteString as B (readFile)-import Graphics.Image.ColorSpace-import Graphics.Image.Interface-import Graphics.Image.IO.Base-import Graphics.Image.IO.Formats import qualified Data.ByteString.Lazy as BL (writeFile, hPut) import System.Directory (createDirectoryIfMissing, getTemporaryDirectory) import System.FilePath (takeExtension, (</>))@@ -52,6 +48,10 @@ import System.Process (readProcess) import Control.Exception (bracket) +import Graphics.Image.ColorSpace+import Graphics.Image.Interface+import Graphics.Image.IO.Base+import Graphics.Image.IO.Formats  -- | External viewing application to use for displaying images. data ExternalViewer =@@ -111,12 +111,12 @@ -- Attempt to read an image in a particular color space that is not supported by -- the format, will result in a compile error. Refer to 'Readable' class for all -- images that can be decoded.-readImageExact :: Readable img format =>+readImageExact :: Readable (Image arr cs e) format =>                   format                   -- ^ A file format that an image should be read as. See                    -- <#g:4 Supported Image Formats>                -> FilePath -- ^ Location of an image.-               -> IO (Either String img)+               -> IO (Either String (Image arr cs e)) readImageExact format path = fmap (decode format) (B.readFile path)  @@ -144,20 +144,20 @@ -- options. Precision and color space, that an image will be written as, is decided -- from image's type. Attempt to write image file in a format that does not -- support color space and precision combination will result in a compile error.-writeImageExact :: Writable img format =>+writeImageExact :: Writable (Image arr cs e) format =>                    format                    -- ^ A file format that an image should be saved in. See                    -- <#g:4 Supported Image Formats>                 -> [SaveOption format] -- ^ A list of format specific options.                 -> FilePath -- ^ Location where an image should be written.-                -> img -- ^ An image to write. Can be a list of images in case+                -> (Image arr cs e) -- ^ An image to write. Can be a list of images in case                        -- of formats supporting animation.                 -> IO () writeImageExact format opts path = BL.writeFile path . encode format opts    -{- | An image is written as a @.tiff@ file into an operating system's temporary-directory and passed as an argument to the external viewer program. -}+-- | An image is written as a @.tiff@ file into an operating system's temporary+-- directory and passed as an argument to the external viewer program. displayImageUsing :: Writable (Image arr cs e) TIF =>                      ExternalViewer -- ^ External viewer to use                   -> Bool -- ^ Should the call be blocking
src/Graphics/Image/IO/Formats/JuicyPixels.hs view
@@ -24,11 +24,13 @@   SaveOption(..),   ) where +import Prelude as P import GHC.Float import Data.Either import qualified Data.Monoid as M (mempty) import Graphics.Image.ColorSpace-import Graphics.Image.Interface hiding (map)+import Graphics.Image.Interface as I+import Graphics.Image.Interface.Vector import Graphics.Image.IO.Base import qualified Data.ByteString as B (ByteString) import qualified Data.ByteString.Lazy as BL (ByteString)@@ -36,7 +38,7 @@ import qualified Codec.Picture.Jpg as JP import qualified Codec.Picture.Types as JP import qualified Codec.Picture.ColorQuant as JP-+import qualified Data.Vector.Storable as V  -- | Bitmap image with @.bmp@ extension. data BMP = BMP@@ -119,13 +121,13 @@ -- Y -> Y (Double)  instance Convertible JP.Pixel8 (Pixel Y Double) where-  convert = toDouble . PixelY+  convert = fmap toDouble . PixelY  instance Convertible JP.Pixel16 (Pixel Y Double) where-  convert = toDouble . PixelY+  convert = fmap toDouble . PixelY  instance Convertible JP.PixelF (Pixel Y Double) where-  convert = toDouble . PixelY+  convert = fmap toDouble . PixelY  instance Convertible JP.PixelYA8 (Pixel Y Double) where   convert = convert . JP.dropTransparency@@ -143,10 +145,10 @@   convert = addAlpha 1 . convert  instance Convertible JP.PixelYA8 (Pixel YA Double) where-  convert (JP.PixelYA8 y a) = toDouble (PixelYA y a)+  convert (JP.PixelYA8 y a) = fmap toDouble (PixelYA y a)  instance Convertible JP.PixelYA16 (Pixel YA Double) where-  convert (JP.PixelYA16 y a) = toDouble (PixelYA y a)+  convert (JP.PixelYA16 y a) = fmap toDouble (PixelYA y a)   -- Color -> Y (Double)@@ -167,10 +169,10 @@   convert = toPixelY . (convert :: JP.PixelRGBF -> Pixel RGB Double)  instance Convertible JP.PixelCMYK8 (Pixel Y Double) where-  convert = toPixelY . toDouble . (convert :: JP.PixelCMYK8 -> Pixel CMYK Word8)+  convert = toPixelY . fmap toDouble . (convert :: JP.PixelCMYK8 -> Pixel CMYK Word8)  instance Convertible JP.PixelCMYK16 (Pixel Y Double) where-  convert = toPixelY . toDouble . (convert :: JP.PixelCMYK16 -> Pixel CMYK Word16)+  convert = toPixelY . fmap toDouble . (convert :: JP.PixelCMYK16 -> Pixel CMYK Word16)  instance Convertible JP.PixelYCbCr8 (Pixel Y Double) where   convert = convert . JP.computeLuma@@ -206,13 +208,13 @@ -- Y -> RGB (Double)  instance Convertible JP.Pixel8 (Pixel RGB Double) where-  convert = toDouble . fromChannel+  convert = broadcastC . toDouble  instance Convertible JP.Pixel16 (Pixel RGB Double) where-  convert = toDouble . fromChannel+  convert = broadcastC . toDouble  instance Convertible JP.PixelF (Pixel RGB Double) where-  convert = toDouble . fromChannel+  convert = broadcastC . toDouble  instance Convertible JP.PixelYA8 (Pixel RGB Double) where   convert = convert . JP.dropTransparency@@ -223,10 +225,10 @@ -- Color -> RGB (Double)  instance Convertible JP.PixelRGB8 (Pixel RGB Double) where-  convert (JP.PixelRGB8 r g b) = toDouble $ PixelRGB r g b+  convert (JP.PixelRGB8 r g b) = fmap toDouble $ PixelRGB r g b  instance Convertible JP.PixelRGB16 (Pixel RGB Double) where-  convert (JP.PixelRGB16 r g b) = toDouble $ PixelRGB r g b+  convert (JP.PixelRGB16 r g b) = fmap toDouble $ PixelRGB r g b  instance Convertible JP.PixelRGBA8 (Pixel RGB Double) where   convert = convert . JP.dropTransparency@@ -285,10 +287,10 @@   convert = addAlpha 1 . convert    instance Convertible JP.PixelRGBA8 (Pixel RGBA Double) where-  convert (JP.PixelRGBA8 r g b a) = toDouble $ PixelRGBA r g b a+  convert (JP.PixelRGBA8 r g b a) = fmap toDouble $ PixelRGBA r g b a    instance Convertible JP.PixelRGBA16 (Pixel RGBA Double) where-  convert (JP.PixelRGBA16 r g b a) = toDouble $ PixelRGBA r g b a+  convert (JP.PixelRGBA16 r g b a) = fmap toDouble $ PixelRGBA r g b a   ---- to JuicyPixels -----@@ -391,232 +393,242 @@  -- BMP Format Reading -instance (Array arr Y Word8, Array arr Binary Bit) => Readable (Image arr Binary Bit) BMP where+instance Readable (Image VS Binary Bit) BMP where   decode _ = fmap toImageBinary . jpImageY8ToImage . JP.decodeBitmap -instance Array arr Y Word8 => Readable (Image arr Y Word8) BMP where+instance Readable (Image VS Y Word8) BMP where   decode _ = jpImageY8ToImage . JP.decodeBitmap -instance Array arr RGB Word8 => Readable (Image arr RGB Word8) BMP where+instance Readable (Image VS RGB Word8) BMP where   decode _ = jpImageRGB8ToImage . JP.decodeBitmap -instance Array arr RGBA Word8 => Readable (Image arr RGBA Word8) BMP where+instance Readable (Image VS RGBA Word8) BMP where   decode _ = jpImageRGBA8ToImage . JP.decodeBitmap -instance Array arr Y Double => Readable (Image arr Y Double) BMP where-  decode _ = jpDynamicImageToImage . JP.decodeBitmap -instance Array arr YA Double => Readable (Image arr YA Double) BMP where-  decode _ = jpDynamicImageToImage . JP.decodeBitmap -instance Array arr RGB Double => Readable (Image arr RGB Double) BMP where-  decode _ = jpDynamicImageToImage . JP.decodeBitmap--instance Array arr RGBA Double => Readable (Image arr RGBA Double) BMP where-  decode _ = jpDynamicImageToImage . JP.decodeBitmap-- -- GIF Format Reading -instance Array arr RGB Word8 => Readable (Image arr RGB Word8) GIF where+instance Readable (Image VS RGB Word8) GIF where   decode _ = jpImageRGB8ToImage . JP.decodeGif -instance Array arr RGBA Word8 => Readable (Image arr RGBA Word8) GIF where+instance Readable (Image VS RGBA Word8) GIF where   decode _ = jpImageRGBA8ToImage . JP.decodeGif -instance Array arr Y Double => Readable (Image arr Y Double) GIF where-  decode _ = jpDynamicImageToImage . JP.decodeGif -instance Array arr YA Double => Readable (Image arr YA Double) GIF where-  decode _ = jpDynamicImageToImage . JP.decodeGif--instance Array arr RGB Double => Readable (Image arr RGB Double) GIF where-  decode _ = jpDynamicImageToImage . JP.decodeGif--instance Array arr RGBA Double => Readable (Image arr RGBA Double) GIF where-  decode _ = jpDynamicImageToImage . JP.decodeGif- -- List of GIF Format frames Reading  decodeGifs :: (Either String JP.DynamicImage -> Either String img)            -> B.ByteString -> Either String [img] decodeGifs decoder = either Left decodeLS . JP.decodeGifImages where     decodeLS ls = if null errs then Right imgs else Left $ unlines errs where-      (errs, imgs) = partitionEithers $ map (decoder . Right) ls+      (errs, imgs) = partitionEithers $ P.map (decoder . Right) ls -instance Array arr RGB Word8 => Readable [Image arr RGB Word8] [GIF] where+instance Readable [Image VS RGB Word8] [GIF] where   decode _ = decodeGifs jpImageRGB8ToImage -instance Array arr RGBA Word8 => Readable [Image arr RGBA Word8] [GIF] where+instance Readable [Image VS RGBA Word8] [GIF] where   decode _ = decodeGifs jpImageRGBA8ToImage -instance Array arr Y Double => Readable [Image arr Y Double] [GIF] where-  decode _ = decodeGifs jpDynamicImageToImage -instance Array arr YA Double => Readable [Image arr YA Double] [GIF] where-  decode _ = decodeGifs jpDynamicImageToImage--instance Array arr RGB Double => Readable [Image arr RGB Double] [GIF] where-  decode _ = decodeGifs jpDynamicImageToImage--instance Array arr RGBA Double => Readable [Image arr RGBA Double] [GIF] where-  decode _ = decodeGifs jpDynamicImageToImage-  -- -- HDR Format Reading -instance Array arr RGB Float => Readable (Image arr RGB Float) HDR where+instance Readable (Image VS RGB Float) HDR where   decode _ = jpImageRGBFToImage . JP.decodeHDR -instance Array arr Y Double => Readable (Image arr Y Double) HDR where-  decode _ = jpDynamicImageToImage . JP.decodeHDR -instance Array arr YA Double => Readable (Image arr YA Double) HDR where-  decode _ = jpDynamicImageToImage . JP.decodeHDR--instance Array arr RGB Double => Readable (Image arr RGB Double) HDR where-  decode _ = jpDynamicImageToImage . JP.decodeHDR--instance Array arr RGBA Double => Readable (Image arr RGBA Double) HDR where-  decode _ = jpDynamicImageToImage . JP.decodeHDR-- -- JPG Format Reading -instance Array arr Y Word8 => Readable (Image arr Y Word8) JPG where+instance Readable (Image VS Y Word8) JPG where   decode _ = jpImageY8ToImage . JP.decodeJpeg -instance Array arr YA Word8 => Readable (Image arr YA Word8) JPG where+instance Readable (Image VS YA Word8) JPG where   decode _ = jpImageYA8ToImage . JP.decodeJpeg -instance Array arr RGB Word8 => Readable (Image arr RGB Word8) JPG where+instance Readable (Image VS RGB Word8) JPG where   decode _ = jpImageRGB8ToImage . JP.decodeJpeg -instance Array arr CMYK Word8 => Readable (Image arr CMYK Word8) JPG where+instance Readable (Image VS CMYK Word8) JPG where   decode _ = jpImageCMYK8ToImage . JP.decodeJpeg -instance Array arr YCbCr Word8 => Readable (Image arr YCbCr Word8) JPG where+instance Readable (Image VS YCbCr Word8) JPG where   decode _ = jpImageYCbCr8ToImage . JP.decodeJpeg -instance Array arr Y Double => Readable (Image arr Y Double) JPG where-  decode _ = jpDynamicImageToImage . JP.decodeJpeg -instance Array arr YA Double => Readable (Image arr YA Double) JPG where-  decode _ = jpDynamicImageToImage . JP.decodeJpeg--instance Array arr RGB Double => Readable (Image arr RGB Double) JPG where-  decode _ = jpDynamicImageToImage . JP.decodeJpeg--instance Array arr RGBA Double => Readable (Image arr RGBA Double) JPG where-  decode _ = jpDynamicImageToImage . JP.decodeJpeg-- -- PNG Format Reading -instance (Array arr Y Word8, Array arr Binary Bit) => Readable (Image arr Binary Bit) PNG where+instance Readable (Image VS Binary Bit) PNG where   decode _ = fmap toImageBinary . jpImageY8ToImage . JP.decodePng -instance Array arr Y Word8 => Readable (Image arr Y Word8) PNG where+instance Readable (Image VS Y Word8) PNG where   decode _ = jpImageY8ToImage . JP.decodePng -instance Array arr Y Word16 => Readable (Image arr Y Word16) PNG where+instance Readable (Image VS Y Word16) PNG where   decode _ = jpImageY16ToImage . JP.decodePng -instance Array arr YA Word8 => Readable (Image arr YA Word8) PNG where+instance Readable (Image VS YA Word8) PNG where   decode _ = jpImageYA8ToImage . JP.decodePng -instance Array arr YA Word16 => Readable (Image arr YA Word16) PNG where+instance Readable (Image VS YA Word16) PNG where   decode _ = jpImageYA16ToImage . JP.decodePng -instance Array arr RGB Word8 => Readable (Image arr RGB Word8) PNG where+instance Readable (Image VS RGB Word8) PNG where   decode _ = jpImageRGB8ToImage . JP.decodePng -instance Array arr RGB Word16 => Readable (Image arr RGB Word16) PNG where+instance Readable (Image VS RGB Word16) PNG where   decode _ = jpImageRGB16ToImage . JP.decodePng -instance Array arr RGBA Word8 => Readable (Image arr RGBA Word8) PNG where+instance Readable (Image VS RGBA Word8) PNG where   decode _ = jpImageRGBA8ToImage . JP.decodePng -instance Array arr RGBA Word16 => Readable (Image arr RGBA Word16) PNG where+instance Readable (Image VS RGBA Word16) PNG where   decode _ = jpImageRGBA16ToImage . JP.decodePng -instance Array arr Y Double => Readable (Image arr Y Double) PNG where-  decode _ = jpDynamicImageToImage . JP.decodePng -instance Array arr YA Double => Readable (Image arr YA Double) PNG where-  decode _ = jpDynamicImageToImage . JP.decodePng--instance Array arr RGB Double => Readable (Image arr RGB Double) PNG where-  decode _ = jpDynamicImageToImage . JP.decodePng--instance Array arr RGBA Double => Readable (Image arr RGBA Double) PNG where-  decode _ = jpDynamicImageToImage . JP.decodePng-- -- TGA Format Reading -instance (Array arr Y Word8, Array arr Binary Bit) => Readable (Image arr Binary Bit) TGA where+instance Readable (Image VS Binary Bit) TGA where   decode _ = fmap toImageBinary . jpImageY8ToImage . JP.decodeTga -instance Array arr Y Word8 => Readable (Image arr Y Word8) TGA where+instance Readable (Image VS Y Word8) TGA where   decode _ = jpImageY8ToImage . JP.decodeTga -instance Array arr RGB Word8 => Readable (Image arr RGB Word8) TGA where+instance Readable (Image VS RGB Word8) TGA where   decode _ = jpImageRGB8ToImage . JP.decodeTga -instance Array arr RGBA Word8 => Readable (Image arr RGBA Word8) TGA where+instance Readable (Image VS RGBA Word8) TGA where   decode _ = jpImageRGBA8ToImage . JP.decodeTga -instance Array arr Y Double => Readable (Image arr Y Double) TGA where-  decode _ = jpDynamicImageToImage . JP.decodeTga -instance Array arr YA Double => Readable (Image arr YA Double) TGA where-  decode _ = jpDynamicImageToImage . JP.decodeTga--instance Array arr RGB Double => Readable (Image arr RGB Double) TGA where-  decode _ = jpDynamicImageToImage . JP.decodeTga--instance Array arr RGBA Double => Readable (Image arr RGBA Double) TGA where-  decode _ = jpDynamicImageToImage . JP.decodeTga-- -- TIF Format Reading -instance (Array arr Y Word8, Array arr Binary Bit) => Readable (Image arr Binary Bit) TIF where+instance Readable (Image VS Binary Bit) TIF where   decode _ = fmap toImageBinary . jpImageY8ToImage . JP.decodeTiff -instance Array arr Y Word8 => Readable (Image arr Y Word8) TIF where+instance Readable (Image VS Y Word8) TIF where   decode _ = jpImageY8ToImage . JP.decodeTiff -instance Array arr Y Word16 => Readable (Image arr Y Word16) TIF where+instance Readable (Image VS Y Word16) TIF where   decode _ = jpImageY16ToImage . JP.decodeTiff -instance Array arr YA Word8 => Readable (Image arr YA Word8) TIF where+instance Readable (Image VS YA Word8) TIF where   decode _ = jpImageYA8ToImage . JP.decodeTiff -instance Array arr YA Word16 => Readable (Image arr YA Word16) TIF where+instance Readable (Image VS YA Word16) TIF where   decode _ = jpImageYA16ToImage . JP.decodeTiff -instance Array arr RGB Word8 => Readable (Image arr RGB Word8) TIF where+instance Readable (Image VS RGB Word8) TIF where   decode _ = jpImageRGB8ToImage . JP.decodeTiff -instance Array arr RGB Word16 => Readable (Image arr RGB Word16) TIF where+instance Readable (Image VS RGB Word16) TIF where   decode _ = jpImageRGB16ToImage . JP.decodeTiff -instance Array arr RGBA Word8 => Readable (Image arr RGBA Word8) TIF where+instance Readable (Image VS RGBA Word8) TIF where   decode _ = jpImageRGBA8ToImage . JP.decodeTiff -instance Array arr RGBA Word16 => Readable (Image arr RGBA Word16) TIF where+instance Readable (Image VS RGBA Word16) TIF where   decode _ = jpImageRGBA16ToImage . JP.decodeTiff -instance Array arr CMYK Word8 => Readable (Image arr CMYK Word8) TIF where+instance Readable (Image VS CMYK Word8) TIF where   decode _ = jpImageCMYK8ToImage . JP.decodeTiff -instance Array arr CMYK Word16 => Readable (Image arr CMYK Word16) TIF where+instance Readable (Image VS CMYK Word16) TIF where   decode _ = jpImageCMYK16ToImage . JP.decodeTiff  +-- To Double precision safe conversion++instance Array arr Y Double => Readable (Image arr Y Double) BMP where+  decode _ = jpDynamicImageToImage . JP.decodeBitmap++instance Array arr YA Double => Readable (Image arr YA Double) BMP where+  decode _ = jpDynamicImageToImage . JP.decodeBitmap++instance Array arr RGB Double => Readable (Image arr RGB Double) BMP where+  decode _ = jpDynamicImageToImage . JP.decodeBitmap++instance Array arr RGBA Double => Readable (Image arr RGBA Double) BMP where+  decode _ = jpDynamicImageToImage . JP.decodeBitmap+++instance Array arr Y Double => Readable (Image arr Y Double) GIF where+  decode _ = jpDynamicImageToImage . JP.decodeGif++instance Array arr YA Double => Readable (Image arr YA Double) GIF where+  decode _ = jpDynamicImageToImage . JP.decodeGif++instance Array arr RGB Double => Readable (Image arr RGB Double) GIF where+  decode _ = jpDynamicImageToImage . JP.decodeGif++instance Array arr RGBA Double => Readable (Image arr RGBA Double) GIF where+  decode _ = jpDynamicImageToImage . JP.decodeGif+++instance Array arr Y Double => Readable [Image arr Y Double] [GIF] where+  decode _ = decodeGifs jpDynamicImageToImage++instance Array arr YA Double => Readable [Image arr YA Double] [GIF] where+  decode _ = decodeGifs jpDynamicImageToImage++instance Array arr RGB Double => Readable [Image arr RGB Double] [GIF] where+  decode _ = decodeGifs jpDynamicImageToImage++instance Array arr RGBA Double => Readable [Image arr RGBA Double] [GIF] where+  decode _ = decodeGifs jpDynamicImageToImage+++instance Array arr Y Double => Readable (Image arr Y Double) HDR where+  decode _ = jpDynamicImageToImage . JP.decodeHDR++instance Array arr YA Double => Readable (Image arr YA Double) HDR where+  decode _ = jpDynamicImageToImage . JP.decodeHDR++instance Array arr RGB Double => Readable (Image arr RGB Double) HDR where+  decode _ = jpDynamicImageToImage . JP.decodeHDR++instance Array arr RGBA Double => Readable (Image arr RGBA Double) HDR where+  decode _ = jpDynamicImageToImage . JP.decodeHDR+++instance Array arr Y Double => Readable (Image arr Y Double) JPG where+  decode _ = jpDynamicImageToImage . JP.decodeJpeg++instance Array arr YA Double => Readable (Image arr YA Double) JPG where+  decode _ = jpDynamicImageToImage . JP.decodeJpeg++instance Array arr RGB Double => Readable (Image arr RGB Double) JPG where+  decode _ = jpDynamicImageToImage . JP.decodeJpeg++instance Array arr RGBA Double => Readable (Image arr RGBA Double) JPG where+  decode _ = jpDynamicImageToImage . JP.decodeJpeg+++instance Array arr Y Double => Readable (Image arr Y Double) PNG where+  decode _ = jpDynamicImageToImage . JP.decodePng++instance Array arr YA Double => Readable (Image arr YA Double) PNG where+  decode _ = jpDynamicImageToImage . JP.decodePng++instance Array arr RGB Double => Readable (Image arr RGB Double) PNG where+  decode _ = jpDynamicImageToImage . JP.decodePng++instance Array arr RGBA Double => Readable (Image arr RGBA Double) PNG where+  decode _ = jpDynamicImageToImage . JP.decodePng+++instance Array arr Y Double => Readable (Image arr Y Double) TGA where+  decode _ = jpDynamicImageToImage . JP.decodeTga++instance Array arr YA Double => Readable (Image arr YA Double) TGA where+  decode _ = jpDynamicImageToImage . JP.decodeTga++instance Array arr RGB Double => Readable (Image arr RGB Double) TGA where+  decode _ = jpDynamicImageToImage . JP.decodeTga++instance Array arr RGBA Double => Readable (Image arr RGBA Double) TGA where+  decode _ = jpDynamicImageToImage . JP.decodeTga++ instance Array arr Y Double => Readable (Image arr Y Double) TIF where   decode _ = jpDynamicImageToImage . JP.decodeTiff @@ -633,118 +645,111 @@  -- General decoding and helper functions -jpImageToImage :: (Array arr cs e, Convertible jpx (Pixel cs e), JP.Pixel jpx) =>-                  JP.Image jpx -> Image arr cs e-jpImageToImage jimg = makeImage (JP.imageHeight jimg, JP.imageWidth jimg) getPx+jpImageToImageUnsafe :: (Array VS cs e, JP.Pixel jpx) =>+                  JP.Image jpx -> Image VS cs e+jpImageToImageUnsafe (JP.Image n m v) = fromStorableVector (m, n) $ V.unsafeCast v++++jpImageToImageSafe :: (Array arr cs e, Convertible jpx (Pixel cs e), JP.Pixel jpx) =>+                      JP.Image jpx -> Image arr cs e+jpImageToImageSafe jimg = makeImage (JP.imageHeight jimg, JP.imageWidth jimg) getPx   where getPx (y, x) = convert $ JP.pixelAt jimg x y  -jpImageY8ToImage :: Array arr Y Word8 =>-                    Either String JP.DynamicImage -> Either String (Image arr Y Word8)-jpImageY8ToImage (Right (JP.ImageY8 jimg)) = Right (jpImageToImage jimg)+jpImageY8ToImage :: Either String JP.DynamicImage -> Either String (Image VS Y Word8)+jpImageY8ToImage (Right (JP.ImageY8 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageY8ToImage jimg = jpCSError "Y8 (Pixel Y Word8)" jimg  -jpImageY16ToImage :: Array arr Y Word16 =>-                     Either String JP.DynamicImage -> Either String (Image arr Y Word16)-jpImageY16ToImage (Right (JP.ImageY16 jimg)) = Right (jpImageToImage jimg)+jpImageY16ToImage :: Either String JP.DynamicImage -> Either String (Image VS Y Word16)+jpImageY16ToImage (Right (JP.ImageY16 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageY16ToImage jimg = jpCSError "Y16 (Pixel Y Word16)" jimg  {- -- No JuicyPixels images are actually read in this type-jpImageYFToImage :: Array arr Y Float =>-                     Either String JP.DynamicImage -> Either String (Image arr Y Float)+jpImageYFToImage :: Either String JP.DynamicImage -> Either String (Image VS Y Float) jpImageYFToImage (Right (JP.ImageYF jimg)) = Right (jpImageToImage jimg) jpImageYFToImage jimg = jpCSError "YF (Pixel Y Float)" jimg -} -jpImageYA8ToImage :: Array arr YA Word8 =>-                    Either String JP.DynamicImage -> Either String (Image arr YA Word8)-jpImageYA8ToImage (Right (JP.ImageYA8 jimg)) = Right (jpImageToImage jimg)+jpImageYA8ToImage :: Either String JP.DynamicImage -> Either String (Image VS YA Word8)+jpImageYA8ToImage (Right (JP.ImageYA8 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageYA8ToImage jimg = jpCSError "YA8 (Pixel YA Word8)" jimg  -jpImageYA16ToImage :: Array arr YA Word16 =>-                     Either String JP.DynamicImage -> Either String (Image arr YA Word16)-jpImageYA16ToImage (Right (JP.ImageYA16 jimg)) = Right (jpImageToImage jimg)+jpImageYA16ToImage :: Either String JP.DynamicImage -> Either String (Image VS YA Word16)+jpImageYA16ToImage (Right (JP.ImageYA16 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageYA16ToImage jimg = jpCSError "YA16 (Pixel YA Word16)" jimg  -jpImageRGB8ToImage :: Array arr RGB Word8 =>-                      Either String JP.DynamicImage -> Either String (Image arr RGB Word8)-jpImageRGB8ToImage (Right (JP.ImageRGB8 jimg)) = Right (jpImageToImage jimg)+jpImageRGB8ToImage :: Either String JP.DynamicImage -> Either String (Image VS RGB Word8)+jpImageRGB8ToImage (Right (JP.ImageRGB8 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageRGB8ToImage jimg = jpCSError "RGB8 (Pixel RGB Word8)" jimg  -jpImageRGB16ToImage :: Array arr RGB Word16 =>-                       Either String JP.DynamicImage -> Either String (Image arr RGB Word16)-jpImageRGB16ToImage (Right (JP.ImageRGB16 jimg)) = Right (jpImageToImage jimg)+jpImageRGB16ToImage :: Either String JP.DynamicImage -> Either String (Image VS RGB Word16)+jpImageRGB16ToImage (Right (JP.ImageRGB16 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageRGB16ToImage jimg = jpCSError "RGB16 (Pixel RGB Word16)" jimg  -jpImageRGBFToImage :: Array arr RGB Float =>-                       Either String JP.DynamicImage -> Either String (Image arr RGB Float)-jpImageRGBFToImage (Right (JP.ImageRGBF jimg)) = Right (jpImageToImage jimg)+jpImageRGBFToImage :: Either String JP.DynamicImage -> Either String (Image VS RGB Float)+jpImageRGBFToImage (Right (JP.ImageRGBF jimg)) = Right (jpImageToImageUnsafe jimg) jpImageRGBFToImage jimg = jpCSError "RGBF (Pixel RGB Float)" jimg  -jpImageRGBA8ToImage :: Array arr RGBA Word8 =>-                      Either String JP.DynamicImage -> Either String (Image arr RGBA Word8)-jpImageRGBA8ToImage (Right (JP.ImageRGBA8 jimg)) = Right (jpImageToImage jimg)+jpImageRGBA8ToImage :: Either String JP.DynamicImage -> Either String (Image VS RGBA Word8)+jpImageRGBA8ToImage (Right (JP.ImageRGBA8 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageRGBA8ToImage jimg = jpCSError "RGBA8 (Pixel RGBA Word8)" jimg  -jpImageRGBA16ToImage :: Array arr RGBA Word16 =>-                       Either String JP.DynamicImage -> Either String (Image arr RGBA Word16)-jpImageRGBA16ToImage (Right (JP.ImageRGBA16 jimg)) = Right (jpImageToImage jimg)+jpImageRGBA16ToImage :: Either String JP.DynamicImage -> Either String (Image VS RGBA Word16)+jpImageRGBA16ToImage (Right (JP.ImageRGBA16 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageRGBA16ToImage jimg = jpCSError "RGBA16 (Pixel RGBA Word16)" jimg  -jpImageYCbCr8ToImage :: Array arr YCbCr Word8 =>-                      Either String JP.DynamicImage -> Either String (Image arr YCbCr Word8)-jpImageYCbCr8ToImage (Right (JP.ImageYCbCr8 jimg)) = Right (jpImageToImage jimg)+jpImageYCbCr8ToImage :: Either String JP.DynamicImage -> Either String (Image VS YCbCr Word8)+jpImageYCbCr8ToImage (Right (JP.ImageYCbCr8 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageYCbCr8ToImage jimg = jpCSError "YCbCr8 (Pixel YCbCr Word8)" jimg  -jpImageCMYK8ToImage :: Array arr CMYK Word8 =>-                      Either String JP.DynamicImage -> Either String (Image arr CMYK Word8)-jpImageCMYK8ToImage (Right (JP.ImageCMYK8 jimg)) = Right (jpImageToImage jimg)+jpImageCMYK8ToImage :: Either String JP.DynamicImage -> Either String (Image VS CMYK Word8)+jpImageCMYK8ToImage (Right (JP.ImageCMYK8 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageCMYK8ToImage jimg = jpCSError "CMYK8 (Pixel CMYK Word8)" jimg  -jpImageCMYK16ToImage :: Array arr CMYK Word16 =>-                      Either String JP.DynamicImage -> Either String (Image arr CMYK Word16)-jpImageCMYK16ToImage (Right (JP.ImageCMYK16 jimg)) = Right (jpImageToImage jimg)+jpImageCMYK16ToImage :: Either String JP.DynamicImage -> Either String (Image VS CMYK Word16)+jpImageCMYK16ToImage (Right (JP.ImageCMYK16 jimg)) = Right (jpImageToImageUnsafe jimg) jpImageCMYK16ToImage jimg = jpCSError "CMYK16 (Pixel CMYK Word16)" jimg   jpDynamicImageToImage' :: (Convertible JP.PixelCMYK16 (Pixel cs e),-                          Convertible JP.PixelCMYK8 (Pixel cs e),-                          Convertible JP.PixelRGB16 (Pixel cs e),-                          Convertible JP.PixelRGB8 (Pixel cs e),-                          Convertible JP.PixelRGBA16 (Pixel cs e),-                          Convertible JP.PixelRGBA8 (Pixel cs e),-                          Convertible JP.PixelRGBF (Pixel cs e),-                          Convertible JP.PixelYA16 (Pixel cs e),-                          Convertible JP.PixelYA8 (Pixel cs e),-                          Convertible JP.PixelYCbCr8 (Pixel cs e),-                          Convertible JP.Pixel16 (Pixel cs e),-                          Convertible JP.Pixel8 (Pixel cs e),-                          Convertible JP.PixelF (Pixel cs e),-                          Array arr cs e) =>-                         JP.DynamicImage -> Image arr cs e-jpDynamicImageToImage' (JP.ImageY8 jimg)     = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageY16 jimg)    = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageYF jimg)     = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageYA8 jimg)    = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageYA16 jimg)   = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageRGB8 jimg)   = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageRGB16 jimg)  = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageRGBF jimg)   = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageRGBA8 jimg)  = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageRGBA16 jimg) = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageYCbCr8 jimg) = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageCMYK8 jimg)  = jpImageToImage jimg-jpDynamicImageToImage' (JP.ImageCMYK16 jimg) = jpImageToImage jimg+                           Convertible JP.PixelCMYK8 (Pixel cs e),+                           Convertible JP.PixelRGB16 (Pixel cs e),+                           Convertible JP.PixelRGB8 (Pixel cs e),+                           Convertible JP.PixelRGBA16 (Pixel cs e),+                           Convertible JP.PixelRGBA8 (Pixel cs e),+                           Convertible JP.PixelRGBF (Pixel cs e),+                           Convertible JP.PixelYA16 (Pixel cs e),+                           Convertible JP.PixelYA8 (Pixel cs e),+                           Convertible JP.PixelYCbCr8 (Pixel cs e),+                           Convertible JP.Pixel16 (Pixel cs e),+                           Convertible JP.Pixel8 (Pixel cs e),+                           Convertible JP.PixelF (Pixel cs e),+                           Array arr cs e) =>+                          JP.DynamicImage -> Image arr cs e+jpDynamicImageToImage' (JP.ImageY8 jimg)     = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageY16 jimg)    = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageYF jimg)     = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageYA8 jimg)    = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageYA16 jimg)   = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageRGB8 jimg)   = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageRGB16 jimg)  = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageRGBF jimg)   = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageRGBA8 jimg)  = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageRGBA16 jimg) = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageYCbCr8 jimg) = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageCMYK8 jimg)  = jpImageToImageSafe jimg+jpDynamicImageToImage' (JP.ImageCMYK16 jimg) = jpImageToImageSafe jimg   jpDynamicImageToImage :: (Convertible JP.PixelCMYK16 (Pixel cs e),@@ -796,73 +801,65 @@ -- Encoding images using JuicyPixels ------------------------------------------- -------------------------------------------------------------------------------- -instance Array arr Y Word8 => Writable (Image arr Y Word8) BMP where-  encode _ _ = JP.encodeBitmap . imageToJPImage (convert :: Pixel Y Word8 -> JP.Pixel8) +instance Writable (Image VS Y Word8) BMP where+  encode _ _ = JP.encodeBitmap . imageToJPImage (undefined :: JP.Pixel8) id -instance Array arr RGB Word8 => Writable (Image arr RGB Word8) BMP where-  encode _ _ = JP.encodeBitmap . imageToJPImage (convert :: Pixel RGB Word8 -> JP.PixelRGB8) +instance Writable (Image VS RGB Word8) BMP where+  encode _ _ = JP.encodeBitmap . imageToJPImage (undefined :: JP.PixelRGB8) id -instance Array arr RGBA Word8 => Writable (Image arr RGBA Word8) BMP where-  encode _ _ = JP.encodeBitmap . imageToJPImage (convert :: Pixel RGBA Word8 -> JP.PixelRGBA8) +instance Writable (Image VS RGBA Word8) BMP where+  encode _ _ = JP.encodeBitmap . imageToJPImage (undefined :: JP.PixelRGBA8) id -instance Array arr Binary Bit => Writable (Image arr Binary Bit) BMP where-  encode _ _ = JP.encodeBitmap . imageToJPImage ((convert :: Pixel Y Word8 -> JP.Pixel8)-                                                 . fromPixelBinary)+instance Writable (Image VS Binary Bit) BMP where+  encode _ _ = JP.encodeBitmap . imageToJPImage (undefined :: JP.Pixel8) fromPixelBinary -instance Array arr Y Double => Writable (Image arr Y Double) BMP where-  encode _ _ = JP.encodeBitmap . imageToJPImage ((convert :: Pixel Y Word8 -> JP.Pixel8)-                                                 . toWord8)+instance Writable (Image VS Y Double) BMP where+  encode _ _ = JP.encodeBitmap . imageToJPImage (undefined :: JP.Pixel8) (fmap toWord8) -instance Array arr YA Double => Writable (Image arr YA Double) BMP where-  encode _ _ = JP.encodeBitmap . imageToJPImage ((convert :: Pixel Y Word8 -> JP.Pixel8)-                                                 . toWord8 . dropAlpha)+instance Writable (Image VS YA Double) BMP where+  encode _ _ = JP.encodeBitmap . imageToJPImage (undefined :: JP.Pixel8)+                                                ((fmap toWord8) . dropAlpha) -instance Array arr RGB Double => Writable (Image arr RGB Double) BMP where-  encode _ _ = JP.encodeBitmap . imageToJPImage ((convert :: Pixel RGB Word8 -> JP.PixelRGB8)-                                                 . toWord8)+instance Writable (Image VS RGB Double) BMP where+  encode _ _ = JP.encodeBitmap . imageToJPImage (undefined :: JP.PixelRGB8) (fmap toWord8) -instance Array arr RGBA Double => Writable (Image arr RGBA Double) BMP where-  encode _ _ = JP.encodeBitmap . imageToJPImage ((convert :: Pixel RGBA Word8 -> JP.PixelRGBA8)-                                                 . toWord8)+instance Writable (Image VS RGBA Double) BMP where+  encode _ _ = JP.encodeBitmap . imageToJPImage (undefined :: JP.PixelRGBA8) (fmap toWord8)  -- Writable GIF -encodeGIF :: Array arr cs e =>-             [SaveOption GIF] -> (Pixel cs e -> JP.PixelRGB8)-             -> Image arr cs e -> BL.ByteString+encodeGIF :: (Array VS cs' e, Array VS cs Word8) =>+             [SaveOption GIF] -> (Pixel cs' e -> Pixel cs Word8)+             -> Image VS cs' e -> BL.ByteString encodeGIF []                     !conv =   either error id . uncurry JP.encodeGifImageWithPalette .-  JP.palettize JP.defaultPaletteOptions . imageToJPImage conv+  JP.palettize JP.defaultPaletteOptions . imageToJPImage (undefined :: JP.PixelRGB8) conv encodeGIF (GIFPalette palOpts:_) !conv =   either error id . uncurry JP.encodeGifImageWithPalette .-  JP.palettize palOpts . imageToJPImage conv+  JP.palettize palOpts . imageToJPImage (undefined :: JP.PixelRGB8) conv  -instance Array arr RGB Word8 => Writable (Image arr RGB Word8) GIF where-  encode _ opts = encodeGIF opts (convert :: Pixel RGB Word8 -> JP.PixelRGB8)+instance Writable (Image VS RGB Word8) GIF where+  encode _ opts = encodeGIF opts id   -instance Array arr Y Double => Writable (Image arr Y Double) GIF where-  encode _ opts = encodeGIF opts ((convert :: Pixel RGB Word8 -> JP.PixelRGB8)-                                  . toWord8 . toPixelRGB)+instance Writable (Image VS Y Double) GIF where+  encode _ opts = encodeGIF opts ((fmap toWord8) . toPixelRGB)     -instance Array arr YA Double => Writable (Image arr YA Double) GIF where-  encode _ opts = encodeGIF opts ((convert :: Pixel RGB Word8 -> JP.PixelRGB8)-                                  . toWord8 . toPixelRGB . dropAlpha)+instance Writable (Image VS YA Double) GIF where+  encode _ opts = encodeGIF opts ((fmap toWord8) . toPixelRGB . dropAlpha) -instance Array arr RGB Double => Writable (Image arr RGB Double) GIF where-  encode _ opts = encodeGIF opts ((convert :: Pixel RGB Word8 -> JP.PixelRGB8)-                                  . toWord8)+instance Writable (Image VS RGB Double) GIF where+  encode _ opts = encodeGIF opts (fmap toWord8) -instance Array arr RGBA Double => Writable (Image arr RGBA Double) GIF where-  encode _ opts = encodeGIF opts ((convert :: Pixel RGB Word8 -> JP.PixelRGB8)-                                  . toWord8 . dropAlpha)+instance Writable (Image VS RGBA Double) GIF where+  encode _ opts = encodeGIF opts ((fmap toWord8) . dropAlpha)  -encodeGIFs :: Array arr cs e =>-              [SaveOption [GIF]] -> (Pixel cs e -> JP.PixelRGB8)-           -> [(JP.GifDelay, Image arr cs e)] -> BL.ByteString+encodeGIFs :: (Array VS cs' e, Array VS cs Word8) =>+              [SaveOption [GIF]] -> (Pixel cs' e -> Pixel cs Word8)+           -> [(JP.GifDelay, Image VS cs' e)] -> BL.ByteString encodeGIFs !opts !conv =-  either error id . JP.encodeGifImages (getGIFsLoop opts) . map palletizeGif where+  either error id . JP.encodeGifImages (getGIFsLoop opts) . P.map palletizeGif where     getGIFsLoop []                   = JP.LoopingNever     getGIFsLoop (GIFsLooping loop:_) = loop     getGIFsLoop (_:xs)               = getGIFsLoop xs    @@ -870,231 +867,209 @@     getGIFsPal (GIFsPalette palOpts:_) = palOpts     getGIFsPal (_:xs)                  = getGIFsPal xs     palletizeGif !(d, img) = (p, d, jimg) where  -      !(jimg, p) = JP.palettize (getGIFsPal opts) $ imageToJPImage conv img+      !(jimg, p) = JP.palettize (getGIFsPal opts) $+                   imageToJPImage (undefined :: JP.PixelRGB8) conv img  -instance Array arr RGB Word8 => Writable [(JP.GifDelay, Image arr RGB Word8)] [GIF] where-  encode _ opts = encodeGIFs opts (convert :: Pixel RGB Word8 -> JP.PixelRGB8)--instance Array arr RGB Double => Writable [(JP.GifDelay, Image arr RGB Double)] [GIF] where-  encode _ opts = encodeGIFs opts ((convert :: Pixel RGB Word8 -> JP.PixelRGB8)-                                   . toWord8)+instance Writable [(JP.GifDelay, Image VS RGB Word8)] [GIF] where+  encode _ opts = encodeGIFs opts id +instance Writable [(JP.GifDelay, Image VS RGB Double)] [GIF] where+  encode _ opts = encodeGIFs opts (fmap toWord8) -- Writable HDR -instance Array arr RGB Float => Writable (Image arr RGB Float) HDR where-  encode _ _ = JP.encodeHDR . imageToJPImage (convert :: Pixel RGB Float -> JP.PixelRGBF) +instance Writable (Image VS RGB Float) HDR where+  encode _ _ = JP.encodeHDR . imageToJPImage (undefined :: JP.PixelRGBF) id -instance Array arr Y Double => Writable (Image arr Y Double) HDR where-  encode _ _ = JP.encodeHDR . imageToJPImage ((convert :: Pixel RGB Float -> JP.PixelRGBF)-                                              . toFloat . toPixelRGB)+instance Writable (Image VS Y Double) HDR where+  encode _ _ = JP.encodeHDR . imageToJPImage (undefined :: JP.PixelRGBF)+                                             (fmap toFloat . toPixelRGB) -instance Array arr YA Double => Writable (Image arr YA Double) HDR where-  encode _ _ = JP.encodeHDR . imageToJPImage ((convert :: Pixel RGB Float -> JP.PixelRGBF)-                                              . toFloat . toPixelRGB . dropAlpha)+instance Writable (Image VS YA Double) HDR where+  encode _ _ = JP.encodeHDR . imageToJPImage (undefined :: JP.PixelRGBF)+                                             (fmap toFloat . toPixelRGB . dropAlpha) -instance Array arr RGB Double => Writable (Image arr RGB Double) HDR where-  encode _ _ = JP.encodeHDR . imageToJPImage ((convert :: Pixel RGB Float -> JP.PixelRGBF)-                                              . toFloat)+instance Writable (Image VS RGB Double) HDR where+  encode _ _ = JP.encodeHDR . imageToJPImage (undefined :: JP.PixelRGBF) (fmap toFloat) -instance Array arr RGBA Double => Writable (Image arr RGBA Double) HDR where-  encode _ _ = JP.encodeHDR . imageToJPImage ((convert :: Pixel RGB Float -> JP.PixelRGBF)-                                              . toFloat . dropAlpha)+instance Writable (Image VS RGBA Double) HDR where+  encode _ _ = JP.encodeHDR . imageToJPImage (undefined :: JP.PixelRGBF)+                                             (fmap toFloat . dropAlpha)    -- Writable JPG  -encodeJPG :: (JP.JpgEncodable px, Array arr cs e) =>-             [SaveOption JPG] -> (Pixel cs e -> px) -> Image arr cs e -> BL.ByteString-encodeJPG []               conv =-  JP.encodeDirectJpegAtQualityWithMetadata 100 M.mempty . imageToJPImage conv-encodeJPG (JPGQuality q:_) conv =-  JP.encodeDirectJpegAtQualityWithMetadata q M.mempty . imageToJPImage conv+encodeJPG+  :: (JP.JpgEncodable px, Array VS cs' e, Array VS cs (JP.PixelBaseComponent px)) =>+     [SaveOption JPG]+     -> px+     -> (Pixel cs' e -> Pixel cs (JP.PixelBaseComponent px))+     -> Image VS cs' e+     -> BL.ByteString+encodeJPG []               t conv =+  JP.encodeDirectJpegAtQualityWithMetadata 100 M.mempty . imageToJPImage t conv+encodeJPG (JPGQuality q:_) t conv =+  JP.encodeDirectJpegAtQualityWithMetadata q M.mempty . imageToJPImage t conv  -instance Array arr Y Word8 => Writable (Image arr Y Word8) JPG where-  encode _ opts = encodeJPG opts (convert :: Pixel Y Word8 -> JP.Pixel8)+instance Writable (Image VS Y Word8) JPG where+  encode _ opts = encodeJPG opts (undefined :: JP.Pixel8) id -instance Array arr RGB Word8 => Writable (Image arr RGB Word8) JPG where-  encode _ opts = encodeJPG opts (convert :: Pixel RGB Word8 -> JP.PixelRGB8) +instance Writable (Image VS RGB Word8) JPG where+  encode _ opts = encodeJPG opts (undefined :: JP.PixelRGB8) id -instance Array arr CMYK Word8 => Writable (Image arr CMYK Word8) JPG where-  encode _ opts = encodeJPG opts (convert :: Pixel CMYK Word8 -> JP.PixelCMYK8) +instance Writable (Image VS CMYK Word8) JPG where+  encode _ opts = encodeJPG opts (undefined :: JP.PixelCMYK8) id                -instance Array arr YCbCr Word8 => Writable (Image arr YCbCr Word8) JPG where-  encode _ opts = encodeJPG opts (convert :: Pixel YCbCr Word8 -> JP.PixelYCbCr8) +instance Writable (Image VS YCbCr Word8) JPG where+  encode _ opts = encodeJPG opts (undefined :: JP.PixelYCbCr8) id -instance Array arr Y Double => Writable (Image arr Y Double) JPG where-  encode _ opts = encodeJPG opts ((convert :: Pixel Y Word8 -> JP.Pixel8)-                                  . toWord8) +instance Writable (Image VS Y Double) JPG where+  encode _ opts = encodeJPG opts (undefined :: JP.Pixel8) (fmap toWord8) -instance Array arr YA Double => Writable (Image arr YA Double) JPG where-  encode _ opts = encodeJPG opts ((convert :: Pixel Y Word8 -> JP.Pixel8)-                                  . toWord8 . dropAlpha) +instance Writable (Image VS YA Double) JPG where+  encode _ opts = encodeJPG opts (undefined :: JP.Pixel8) ((fmap toWord8) . dropAlpha)  -instance Array arr RGB Double => Writable (Image arr RGB Double) JPG where-  encode _ opts = encodeJPG opts ((convert :: Pixel RGB Word8 -> JP.PixelRGB8)-                                  . toWord8) +instance Writable (Image VS RGB Double) JPG where+  encode _ opts = encodeJPG opts (undefined :: JP.PixelRGB8) (fmap toWord8) -instance Array arr RGBA Double => Writable (Image arr RGBA Double) JPG where-  encode _ opts = encodeJPG opts ((convert :: Pixel RGB Word8 -> JP.PixelRGB8)-                                  . toWord8 . dropAlpha) +instance Writable (Image VS RGBA Double) JPG where+  encode _ opts = encodeJPG opts (undefined :: JP.PixelRGB8) ((fmap toWord8) . dropAlpha)    -- Writable PNG -instance Array arr Binary Bit => Writable (Image arr Binary Bit) PNG where-  encode _ _ = JP.encodePng . imageToJPImage ((convert :: Pixel Y Word8 -> JP.Pixel8) -                                              . fromPixelBinary)+instance Writable (Image VS Binary Bit) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.Pixel8) fromPixelBinary   -instance Array arr Y Word8 => Writable (Image arr Y Word8) PNG where-  encode _ _ = JP.encodePng . imageToJPImage (convert :: Pixel Y Word8 -> JP.Pixel8) +instance Writable (Image VS Y Word8) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.Pixel8) id -instance Array arr Y Word16 => Writable (Image arr Y Word16) PNG where-  encode _ _ = JP.encodePng . imageToJPImage (convert :: Pixel Y Word16 -> JP.Pixel16) +instance Writable (Image VS Y Word16) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.Pixel16) id -instance Array arr YA Word8 => Writable (Image arr YA Word8) PNG where-  encode _ _ = JP.encodePng . imageToJPImage (convert :: Pixel YA Word8 -> JP.PixelYA8) +instance Writable (Image VS YA Word8) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.PixelYA8) id -instance Array arr YA Word16 => Writable (Image arr YA Word16) PNG where-  encode _ _ = JP.encodePng . imageToJPImage (convert :: Pixel YA Word16 -> JP.PixelYA16) +instance Writable (Image VS YA Word16) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.PixelYA16) id -instance Array arr RGB Word8 => Writable (Image arr RGB Word8) PNG where-  encode _ _ = JP.encodePng . imageToJPImage (convert :: Pixel RGB Word8 -> JP.PixelRGB8) +instance Writable (Image VS RGB Word8) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.PixelRGB8) id -instance Array arr RGB Word16 => Writable (Image arr RGB Word16) PNG where-  encode _ _ = JP.encodePng . imageToJPImage (convert :: Pixel RGB Word16 -> JP.PixelRGB16) +instance Writable (Image VS RGB Word16) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.PixelRGB16) id -instance Array arr RGBA Word8 => Writable (Image arr RGBA Word8) PNG where-  encode _ _ = JP.encodePng . imageToJPImage (convert :: Pixel RGBA Word8 -> JP.PixelRGBA8) +instance Writable (Image VS RGBA Word8) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.PixelRGBA8) id -instance Array arr RGBA Word16 => Writable (Image arr RGBA Word16) PNG where-  encode _ _ = JP.encodePng . imageToJPImage (convert :: Pixel RGBA Word16 -> JP.PixelRGBA16) +instance Writable (Image VS RGBA Word16) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.PixelRGBA16) id  -instance Array arr Y Double => Writable (Image arr Y Double) PNG where-  encode _ _ = JP.encodePng . imageToJPImage ((convert :: Pixel Y Word16 -> JP.Pixel16)-                                              . toWord16)+instance Writable (Image VS Y Double) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.Pixel16) (fmap toWord16) -instance Array arr YA Double => Writable (Image arr YA Double) PNG where-  encode _ _ = JP.encodePng . imageToJPImage ((convert :: Pixel YA Word16 -> JP.PixelYA16)-                                              . toWord16)+instance Writable (Image VS YA Double) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.PixelYA16) (fmap toWord16) -instance Array arr RGB Double => Writable (Image arr RGB Double) PNG where-  encode _ _ = JP.encodePng . imageToJPImage ((convert :: Pixel RGB Word16 -> JP.PixelRGB16)-                                              . toWord16)+instance Writable (Image VS RGB Double) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.PixelRGB16) (fmap toWord16) -instance Array arr RGBA Double => Writable (Image arr RGBA Double) PNG where-  encode _ _ = JP.encodePng . imageToJPImage ((convert :: Pixel RGBA Word16 -> JP.PixelRGBA16)-                                              . toWord16)+instance Writable (Image VS RGBA Double) PNG where+  encode _ _ = JP.encodePng . imageToJPImage (undefined :: JP.PixelRGBA16) (fmap toWord16)  -- Writable TGA -instance Array arr Binary Bit => Writable (Image arr Binary Bit) TGA where-  encode _ _ = JP.encodeTga . imageToJPImage ((convert :: Pixel Y Word8 -> JP.Pixel8)-                                              . fromPixelBinary)+instance Writable (Image VS Binary Bit) TGA where+  encode _ _ = JP.encodeTga . imageToJPImage (undefined :: JP.Pixel8) fromPixelBinary   -instance Array arr Y Word8 => Writable (Image arr Y Word8) TGA where-  encode _ _ = JP.encodeTga . imageToJPImage (convert :: Pixel Y Word8 -> JP.Pixel8) +instance Writable (Image VS Y Word8) TGA where+  encode _ _ = JP.encodeTga . imageToJPImage (undefined :: JP.Pixel8) id -instance Array arr RGB Word8 => Writable (Image arr RGB Word8) TGA where-  encode _ _ = JP.encodeTga . imageToJPImage (convert :: Pixel RGB Word8 -> JP.PixelRGB8) +instance Writable (Image VS RGB Word8) TGA where+  encode _ _ = JP.encodeTga . imageToJPImage (undefined :: JP.PixelRGB8) id -instance Array arr RGBA Word8 => Writable (Image arr RGBA Word8) TGA where-  encode _ _ = JP.encodeTga . imageToJPImage (convert :: Pixel RGBA Word8 -> JP.PixelRGBA8) +instance Writable (Image VS RGBA Word8) TGA where+  encode _ _ = JP.encodeTga . imageToJPImage (undefined :: JP.PixelRGBA8) id  -instance Array arr Y Double => Writable (Image arr Y Double) TGA where-  encode _ _ = JP.encodeTga . imageToJPImage ((convert :: Pixel Y Word8 -> JP.Pixel8)-                                              . toWord8)+instance Writable (Image VS Y Double) TGA where+  encode _ _ = JP.encodeTga . imageToJPImage (undefined :: JP.Pixel8) (fmap toWord8) -instance Array arr YA Double => Writable (Image arr YA Double) TGA where-  encode _ _ = JP.encodeTga . imageToJPImage ((convert :: Pixel Y Word8 -> JP.Pixel8)-                                              . toWord8 . dropAlpha)+instance Writable (Image VS YA Double) TGA where+  encode _ _ = JP.encodeTga . imageToJPImage (undefined :: JP.Pixel8) ((fmap toWord8) . dropAlpha) -instance Array arr RGB Double => Writable (Image arr RGB Double) TGA where-  encode _ _ = JP.encodeTga . imageToJPImage ((convert :: Pixel RGB Word8 -> JP.PixelRGB8)-                                              . toWord8)+instance Writable (Image VS RGB Double) TGA where+  encode _ _ = JP.encodeTga . imageToJPImage (undefined :: JP.PixelRGB8) (fmap toWord8) -instance Array arr RGBA Double => Writable (Image arr RGBA Double) TGA where-  encode _ _ = JP.encodeTga . imageToJPImage ((convert :: Pixel RGBA Word8 -> JP.PixelRGBA8)-                                              . toWord8)+instance Writable (Image VS RGBA Double) TGA where+  encode _ _ = JP.encodeTga . imageToJPImage (undefined :: JP.PixelRGBA8) (fmap toWord8)  -- Writable TIF -instance Array arr Y Word8 => Writable (Image arr Y Word8) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel Y Word8 -> JP.Pixel8) +instance Writable (Image VS Y Word8) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.Pixel8) id -instance Array arr Y Word16 => Writable (Image arr Y Word16) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel Y Word16 -> JP.Pixel16) +instance Writable (Image VS Y Word16) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.Pixel16) id -instance Array arr YA Word8 => Writable (Image arr YA Word8) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel YA Word8 -> JP.PixelYA8) +instance Writable (Image VS YA Word8) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelYA8) id -instance Array arr YA Word16 => Writable (Image arr YA Word16) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel YA Word16 -> JP.PixelYA16) +instance Writable (Image VS YA Word16) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelYA16) id -instance Array arr RGB Word8 => Writable (Image arr RGB Word8) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel RGB Word8 -> JP.PixelRGB8) +instance Writable (Image VS RGB Word8) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelRGB8) id -instance Array arr RGB Word16 => Writable (Image arr RGB Word16) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel RGB Word16 -> JP.PixelRGB16) +instance Writable (Image VS RGB Word16) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelRGB16) id -instance Array arr RGBA Word8 => Writable (Image arr RGBA Word8) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel RGBA Word8 -> JP.PixelRGBA8) +instance Writable (Image VS RGBA Word8) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelRGBA8) id -instance Array arr RGBA Word16 => Writable (Image arr RGBA Word16) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel RGBA Word16 -> JP.PixelRGBA16) +instance Writable (Image VS RGBA Word16) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelRGBA16) id -instance Array arr YCbCr Word8 => Writable (Image arr YCbCr Word8) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel YCbCr Word8 -> JP.PixelYCbCr8)+instance Writable (Image VS YCbCr Word8) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelYCbCr8) id   -instance Array arr CMYK Word8 => Writable (Image arr CMYK Word8) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel CMYK Word8 -> JP.PixelCMYK8) +instance Writable (Image VS CMYK Word8) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelCMYK8) id -instance Array arr CMYK Word16 => Writable (Image arr CMYK Word16) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage (convert :: Pixel CMYK Word16 -> JP.PixelCMYK16) +instance Writable (Image VS CMYK Word16) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelCMYK16) id  -instance Array arr Binary Bit => Writable (Image arr Binary Bit) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage ((convert :: Pixel Y Word8 -> JP.Pixel8)-                                               . fromPixelBinary)+instance Writable (Image VS Binary Bit) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.Pixel8) fromPixelBinary   -instance Array arr Y Double => Writable (Image arr Y Double) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage ((convert :: Pixel Y Word16 -> JP.Pixel16)-                                               . toWord16)+instance Writable (Image VS Y Double) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.Pixel16) (fmap toWord16) -instance Array arr YA Double => Writable (Image arr YA Double) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage ((convert :: Pixel YA Word16 -> JP.PixelYA16)-                                               . toWord16)+instance Writable (Image VS YA Double) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelYA16) (fmap toWord16) -instance Array arr RGB Double => Writable (Image arr RGB Double) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage ((convert :: Pixel RGB Word16 -> JP.PixelRGB16)-                                               . toWord16)+instance Writable (Image VS RGB Double) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelRGB16) (fmap toWord16) -instance Array arr RGBA Double => Writable (Image arr RGBA Double) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage ((convert :: Pixel RGBA Word16 -> JP.PixelRGBA16)-                                               . toWord16)+instance Writable (Image VS RGBA Double) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelRGBA16) (fmap toWord16) -instance Array arr YCbCr Double => Writable (Image arr YCbCr Double) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage ((convert :: Pixel YCbCr Word8 -> JP.PixelYCbCr8)-                                               . toWord8)+instance Writable (Image VS YCbCr Double) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelYCbCr8) (fmap toWord8) -instance Array arr CMYK Double => Writable (Image arr CMYK Double) TIF where-  encode _ _ = JP.encodeTiff . imageToJPImage ((convert :: Pixel CMYK Word16 -> JP.PixelCMYK16)-                                               . toWord16)+instance Writable (Image VS CMYK Double) TIF where+  encode _ _ = JP.encodeTiff . imageToJPImage (undefined :: JP.PixelCMYK16) (fmap toWord16)   -imageToJPImage :: (JP.Pixel a, Array arr cs e) =>-                  (Pixel cs e -> a) -> Image arr cs e -> JP.Image a-imageToJPImage !f !imgD = JP.generateImage g n m-  where-    !(m, n) = dims imgD-    !img = toManifest imgD-    g !j !i = f (index img (i, j))-    {-# INLINE g #-}+imageToJPImage :: (JP.Pixel a, Array VS cs' e, Array VS cs (JP.PixelBaseComponent a)) =>+                  a -> (Pixel cs' e -> Pixel cs (JP.PixelBaseComponent a)) -> Image VS cs' e -> JP.Image a+imageToJPImage _ f !img = JP.Image n m $ V.unsafeCast $ toStorableVector $ I.map f img where+  !(m, n) = dims img {-# INLINE imageToJPImage #-}  
src/Graphics/Image/IO/Formats/Netpbm.hs view
@@ -18,11 +18,12 @@  import Graphics.Image.ColorSpace import Graphics.Image.Interface hiding (map)+import Graphics.Image.Interface.Vector import Graphics.Image.IO.Base import Foreign.Storable (Storable) import qualified Data.ByteString as B (ByteString) import qualified Graphics.Netpbm as PNM-import qualified Data.Vector.Storable as VS ((!), Vector)+import qualified Data.Vector.Storable as V   -- | Netpbm: portable bitmap image with @.pbm@ extension.@@ -80,16 +81,16 @@   convert (PNM.PbmPixel bool) = PixelY $ if bool then 0 else 1    instance Convertible PNM.PgmPixel8 (Pixel Y Double) where-  convert (PNM.PgmPixel8 w8) = toDouble . PixelY $ w8+  convert (PNM.PgmPixel8 w8) = PixelY $ toDouble w8  instance Convertible PNM.PgmPixel16 (Pixel Y Double) where-  convert (PNM.PgmPixel16 w16) = toDouble . PixelY $ w16+  convert (PNM.PgmPixel16 w16) = PixelY $ toDouble w16  instance Convertible PNM.PpmPixelRGB8 (Pixel Y Double) where-  convert (PNM.PpmPixelRGB8 r g b) = toPixelY . toDouble $ PixelRGB r g b+  convert (PNM.PpmPixelRGB8 r g b) = toPixelY . fmap toDouble $ PixelRGB r g b  instance Convertible PNM.PpmPixelRGB16 (Pixel Y Double) where-  convert (PNM.PpmPixelRGB16 r g b) = toPixelY . toDouble $ PixelRGB r g b+  convert (PNM.PpmPixelRGB16 r g b) = toPixelY . fmap toDouble $ PixelRGB r g b  -- -> YA (Double) @@ -120,10 +121,10 @@   convert = toPixelRGB . (convert :: PNM.PgmPixel16 -> Pixel Y Double)  instance Convertible PNM.PpmPixelRGB8 (Pixel RGB Double) where-  convert (PNM.PpmPixelRGB8 r g b) = toDouble $ PixelRGB r g b+  convert (PNM.PpmPixelRGB8 r g b) = fmap toDouble $ PixelRGB r g b  instance Convertible PNM.PpmPixelRGB16 (Pixel RGB Double) where-  convert (PNM.PpmPixelRGB16 r g b) = toDouble $ PixelRGB r g b+  convert (PNM.PpmPixelRGB16 r g b) = fmap toDouble $ PixelRGB r g b   -- -> RGBA (Double)@@ -190,35 +191,35 @@  -- BMP Format Reading (exact) -instance Array arr Binary Bit => Readable (Image arr Binary Bit) PBM where+instance Readable (Image VS Binary Bit) PBM where   decode _ = either Left (ppmToImageUsing pnmDataPBMToImage . head) . decodePnm -instance Array arr Y Word8 => Readable (Image arr Y Word8) PGM where+instance Readable (Image VS Y Word8) PGM where   decode _ = either Left (ppmToImageUsing pnmDataPGM8ToImage . head) . decodePnm -instance Array arr Y Word16 => Readable (Image arr Y Word16) PGM where+instance Readable (Image VS Y Word16) PGM where   decode _ = either Left (ppmToImageUsing pnmDataPGM16ToImage . head) . decodePnm -instance Array arr RGB Word8 => Readable (Image arr RGB Word8) PPM where+instance Readable (Image VS RGB Word8) PPM where   decode _ = either Left (ppmToImageUsing pnmDataPPM8ToImage . head) . decodePnm -instance Array arr RGB Word16 => Readable (Image arr RGB Word16) PPM where+instance Readable (Image VS RGB Word16) PPM where   decode _ = either Left (ppmToImageUsing pnmDataPPM16ToImage . head) . decodePnm  -instance Array arr Binary Bit => Readable [Image arr Binary Bit] [PBM] where+instance Readable [Image VS Binary Bit] [PBM] where   decode _ = pnmToImagesUsing pnmDataPBMToImage -instance Array arr Y Word8 => Readable [Image arr Y Word8] [PGM] where+instance Readable [Image VS Y Word8] [PGM] where   decode _ = pnmToImagesUsing pnmDataPGM8ToImage -instance Array arr Y Word16 => Readable [Image arr Y Word16] [PGM] where+instance Readable [Image VS Y Word16] [PGM] where   decode _ = pnmToImagesUsing pnmDataPGM16ToImage -instance Array arr RGB Word8 => Readable [Image arr RGB Word8] [PPM] where+instance Readable [Image VS RGB Word8] [PPM] where   decode _ = pnmToImagesUsing pnmDataPPM8ToImage -instance Array arr RGB Word16 => Readable [Image arr RGB Word16] [PPM] where+instance Readable [Image VS RGB Word16] [PPM] where   decode _ = pnmToImagesUsing pnmDataPPM16ToImage  @@ -228,8 +229,8 @@   fmap (map (either error id . ppmToImageUsing conv)) . decodePnm  -getPx :: (Storable a, Convertible a b) => VS.Vector a -> Int -> (Int, Int) -> b-getPx v w (i, j) = convert (v VS.! (i * w + j))+getPx :: (Storable a, Convertible a b) => V.Vector a -> Int -> (Int, Int) -> b+getPx v w (i, j) = convert (v V.! (i * w + j))   pnmDataToImage :: (Array arr cs e, Convertible PNM.PbmPixel px,@@ -243,29 +244,30 @@ pnmDataToImage conv w h (PNM.PpmPixelDataRGB16 v) = makeImage (h, w) (conv . getPx v w)  -pnmDataPBMToImage :: (Array arr cs e, Convertible PNM.PbmPixel (Pixel cs e)) =>-                     Int -> Int -> PNM.PpmPixelData -> Either String (Image arr cs e)-pnmDataPBMToImage w h (PNM.PbmPixelData v) = Right $ makeImage (h, w) (getPx v w)+makeImageUnsafe+  :: (Storable a, Array VS cs e)+  => (Int, Int) -> V.Vector a -> Image VS cs e+makeImageUnsafe sz = fromStorableVector sz . V.unsafeCast+++pnmDataPBMToImage :: Int -> Int -> PNM.PpmPixelData -> Either String (Image VS Binary Bit)+pnmDataPBMToImage w h (PNM.PbmPixelData v) = Right $ makeImageUnsafe (h, w) v pnmDataPBMToImage _ _ d                    = pnmCSError "Binary (Pixel Binary Bit)" d -pnmDataPGM8ToImage :: (Array arr cs e, Convertible PNM.PgmPixel8 (Pixel cs e)) =>-                      Int -> Int -> PNM.PpmPixelData -> Either String (Image arr cs e)-pnmDataPGM8ToImage w h (PNM.PgmPixelData8 v) = Right $ makeImage (h, w) (getPx v w)+pnmDataPGM8ToImage :: Int -> Int -> PNM.PpmPixelData -> Either String (Image VS Y Word8)+pnmDataPGM8ToImage w h (PNM.PgmPixelData8 v) = Right $ makeImageUnsafe (h, w) v pnmDataPGM8ToImage _ _ d                     = pnmCSError "Y8 (Pixel Y Word8)" d -pnmDataPGM16ToImage :: (Array arr cs e, Convertible PNM.PgmPixel16 (Pixel cs e)) =>-                       Int -> Int -> PNM.PpmPixelData -> Either String (Image arr cs e)-pnmDataPGM16ToImage w h (PNM.PgmPixelData16 v) = Right $ makeImage (h, w) (getPx v w)+pnmDataPGM16ToImage :: Int -> Int -> PNM.PpmPixelData -> Either String (Image VS Y Word16)+pnmDataPGM16ToImage w h (PNM.PgmPixelData16 v) = Right $ makeImageUnsafe (h, w) v pnmDataPGM16ToImage _ _ d                      = pnmCSError "Y16 (Pixel Y Word16)" d -pnmDataPPM8ToImage :: (Array arr cs e, Convertible PNM.PpmPixelRGB8 (Pixel cs e)) =>-                      Int -> Int -> PNM.PpmPixelData -> Either String (Image arr cs e)-pnmDataPPM8ToImage w h (PNM.PpmPixelDataRGB8 v) = Right $ makeImage (h, w) (getPx v w)+pnmDataPPM8ToImage :: Int -> Int -> PNM.PpmPixelData -> Either String (Image VS RGB Word8)+pnmDataPPM8ToImage w h (PNM.PpmPixelDataRGB8 v) = Right $ makeImageUnsafe (h, w) v pnmDataPPM8ToImage _ _ d                        = pnmCSError "RGB8 (Pixel RGB Word8)" d -pnmDataPPM16ToImage :: (Array arr cs e, Convertible PNM.PpmPixelRGB16 (Pixel cs e)) =>-                       Int -> Int -> PNM.PpmPixelData -> Either String (Image arr cs e)-pnmDataPPM16ToImage w h (PNM.PpmPixelDataRGB16 v) = Right $ makeImage (h, w) (getPx v w)+pnmDataPPM16ToImage :: Int -> Int -> PNM.PpmPixelData -> Either String (Image VS RGB Word16)+pnmDataPPM16ToImage w h (PNM.PpmPixelDataRGB16 v) = Right $ makeImageUnsafe (h, w) v pnmDataPPM16ToImage _ _ d                         = pnmCSError "RGB16 (Pixel RGB Word16)" d  
src/Graphics/Image/IO/Histogram.hs view
@@ -11,24 +11,26 @@ -- Portability : non-portable -- module Graphics.Image.IO.Histogram (-  Histogram(..), Histograms, getHistograms, getHistogram,+  Histogram(..), Histograms, ChannelColour(..), getHistograms, getHistogram,   displayHistograms, writeHistograms   ) where  import Prelude as P  import Control.Concurrent (forkIO) import Control.Monad (void)-import Graphics.Image.Interface as I-import Graphics.Image.IO-import Graphics.Image.ColorSpace-import Graphics.Rendering.Chart.Easy-import Graphics.Rendering.Chart.Backend.Diagrams import qualified Data.Colour as C+import qualified Data.Colour.Names as C import qualified Data.Vector.Unboxed as V import System.Directory (getTemporaryDirectory) import System.FilePath ((</>)) import System.IO.Temp (createTempDirectory) +import Graphics.Image.Interface as I+import Graphics.Image.IO+import Graphics.Image.ColorSpace+import Graphics.Rendering.Chart.Easy+import Graphics.Rendering.Chart.Backend.Diagrams+ #if MIN_VERSION_vector(0,11,0) import Data.Vector.Unboxed.Mutable (modify) #else@@ -42,6 +44,12 @@ #endif  +class ChannelColour cs where+ +  -- | Get a pure colour representation of a channel.+  csColour :: cs -> C.AlphaColour Double++ -- | A single channel histogram of an image. data Histogram = Histogram { hBins :: V.Vector Int                              -- ^ Vector containing pixel counts. Index of a@@ -57,8 +65,8 @@ type Histograms = [Histogram]  -- | Create a histogram per channel with 256 bins each.-getHistograms :: forall arr cs e . (MArray arr Gray e, Array arr Gray e, -                                    MArray arr cs e, Array arr cs e, Elevator e) =>+getHistograms :: forall arr cs e . (ChannelColour cs, MArray arr Gray e, Array arr Gray e, +                                    MArray arr cs e, Array arr cs e) =>                  Image arr cs e               -> Histograms getHistograms = P.zipWith setCh (enumFrom (toEnum 0) :: [cs]) . P.map getHistogram . toGrayImages@@ -66,7 +74,7 @@                        , hColour = csColour cs }  -- | Generate a histogram with 256 bins for a single channel Gray image.-getHistogram :: (MArray arr Gray e, Elevator e) =>+getHistogram :: MArray arr Gray e =>                 Image arr Gray e              -> Histogram getHistogram img = Histogram { hBins = V.modify countBins $@@ -74,7 +82,7 @@                                        (1 + fromIntegral (maxBound :: Word8)) (0 :: Int)                              , hName = show Gray                              , hColour = csColour Gray } where-  incBin v (toWord8 -> PixelGray g) = modify v (+1) $ fromIntegral g+  incBin v (PixelGray g) = modify v (+1) $ fromIntegral (toWord8 g)   countBins v = I.mapM_ (incBin v) img    @@ -119,3 +127,64 @@   if block     then display     else void $ forkIO display++instance ChannelColour Gray where+  csColour _ = C.opaque C.darkgray++instance ChannelColour Y where+  csColour _ = C.opaque C.darkgray++instance ChannelColour YA where+  csColour LumaYA  = csColour LumaY+  csColour AlphaYA = C.opaque C.gray+++instance ChannelColour RGB where+  csColour RedRGB   = C.opaque C.red+  csColour GreenRGB = C.opaque C.green+  csColour BlueRGB  = C.opaque C.blue++instance ChannelColour RGBA where+  csColour RedRGBA   = C.opaque C.red+  csColour GreenRGBA = C.opaque C.green+  csColour BlueRGBA  = C.opaque C.blue+  csColour AlphaRGBA = C.opaque C.gray+++instance ChannelColour HSI where+  csColour HueHSI = C.opaque C.purple+  csColour SatHSI = C.opaque C.orange+  csColour IntHSI = C.opaque C.darkblue++instance ChannelColour HSIA where+  csColour HueHSIA = C.opaque C.purple+  csColour SatHSIA = C.opaque C.orange+  csColour IntHSIA = C.opaque C.darkblue+  csColour AlphaHSIA = C.opaque C.gray+++instance ChannelColour CMYK where+  csColour CyanCMYK = C.opaque C.cyan+  csColour MagCMYK  = C.opaque C.magenta+  csColour YelCMYK  = C.opaque C.yellow+  csColour KeyCMYK  = C.opaque C.black++instance ChannelColour CMYKA where+  csColour CyanCMYKA  = csColour CyanCMYK+  csColour MagCMYKA   = csColour MagCMYK+  csColour YelCMYKA   = csColour YelCMYK+  csColour KeyCMYKA   = csColour KeyCMYK+  csColour AlphaCMYKA = C.opaque C.grey+++instance ChannelColour YCbCr where+  csColour LumaYCbCr  = C.opaque C.darkgray+  csColour CBlueYCbCr = C.opaque C.darkblue+  csColour CRedYCbCr  = C.opaque C.darkred+++instance ChannelColour YCbCrA where+  csColour LumaYCbCrA  = csColour LumaYCbCr+  csColour CBlueYCbCrA = csColour CBlueYCbCr+  csColour CRedYCbCrA  = csColour CRedYCbCr+  csColour AlphaYCbCrA = C.opaque C.gray
src/Graphics/Image/Interface.hs view
@@ -8,86 +8,103 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} #if __GLASGOW_HASKELL__ >= 800-  {-# OPTIONS_GHC -Wno-redundant-constraints #-}-  {-# LANGUAGE UndecidableSuperClasses #-}+    {-# OPTIONS_GHC -Wno-redundant-constraints #-}+    {-# LANGUAGE UndecidableSuperClasses #-} #endif {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Image.Interface--- Copyright   : (c) Alexey Kuleshevich 2016+-- Copyright   : (c) Alexey Kuleshevich 2017 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental -- Portability : non-portable -- module Graphics.Image.Interface (-  ColorSpace(..), Alpha(..), Elevator(..),+  Pixel, ColorSpace(..), AlphaSpace(..), Elevator(..),   BaseArray(..), Array(..), MArray(..),   Exchangable(..), exchangeFrom,   defaultIndex, borderIndex, maybeIndex, Border(..), handleBorderIndex,+  fromIx, toIx, checkDims+#if !MIN_VERSION_base(4,8,0)+  , module Control.Applicative+  , Foldable+#endif   ) where  import Prelude hiding (and, map, zipWith, sum, product) #if !MIN_VERSION_base(4,8,0)-import Data.Monoid (Monoid)-import Data.Foldable (Foldable(foldMap))+import Control.Applicative #endif+import Data.Maybe (fromMaybe)+import Data.Foldable import GHC.Exts (Constraint) import Data.Typeable (Typeable, showsTypeRep, typeOf)-import Control.DeepSeq (NFData(rnf))+import Control.DeepSeq (NFData(rnf), deepseq) import Data.Word-import Control.Applicative+ import Control.Monad.Primitive (PrimMonad (..))-import qualified Data.Colour as C  --- | This class has all included color spaces installed into it and is also--- intended for implementing any other possible custom color spaces. Every--- instance of this class automatically installs an associated 'Pixel' into--- 'Num', 'Fractional', 'Floating', 'Functor', 'Applicative' and 'Foldable',--- which in turn make it possible to be used by the rest of the library.-class (Eq cs, Enum cs, Show cs, Typeable cs) => ColorSpace cs where-  -  -- | Representation of a pixel, such that it can be an element of any-  -- Array. Which is usally a tuple of channels or a channel itself for single-  -- channel color spaces.-  type PixelElt cs e+-- | A Pixel family with a color space and a precision of elements.+data family Pixel cs e :: * -  -- | A concrete Pixel representation for a particular color space.-  data Pixel cs e -  -- | Construt a pixel by replicating a same value among all of the channels.-  fromChannel :: e -> Pixel cs e+class (Eq cs, Enum cs, Show cs, Typeable cs, Elevator e, Typeable e) => ColorSpace cs e where+  +  type Components cs e    -- | Convert a Pixel to a representation suitable for storage as an unboxed   -- element, usually a tuple of channels.-  toElt :: Pixel cs e -> PixelElt cs e+  toComponents :: Pixel cs e -> Components cs e    -- | Convert from an elemnt representation back to a Pixel.-  fromElt :: PixelElt cs e -> Pixel cs e+  fromComponents :: Components cs e -> Pixel cs e -  -- | Retrieve Pixel's channel value-  getPxCh :: Pixel cs e -> cs -> e+  -- | Construt a pixel by replicating a same value among all of the components.+  broadcastC :: e -> Pixel cs e++  -- | Retrieve Pixel's component value+  getPxC :: Pixel cs e -> cs -> e   -  -- | Map a channel aware function over all Pixel's channels.-  chOp :: (cs -> e' -> e) -> Pixel cs e' -> Pixel cs e +  -- | Set Pixel's component value+  setPxC :: Pixel cs e -> cs -> e -> Pixel cs e+  +  -- | Map a channel aware function over all Pixel's components.+  mapPxC :: (cs -> e -> e) -> Pixel cs e -> Pixel cs e  -  -- | Map a function over all Pixel's channels.-  pxOp :: (e' -> e) -> Pixel cs e' -> Pixel cs e+  -- | Map a function over all Pixel's componenets.+  mapPx :: (e -> e) -> Pixel cs e -> Pixel cs e -  -- | Function application to a Pixel.-  chApp :: Pixel cs (e' -> e) -> Pixel cs e' -> Pixel cs e+  -- | Zip two Pixels with a function.+  zipWithPx :: (e -> e -> e) -> Pixel cs e -> Pixel cs e -> Pixel cs e -  -- | A pixel eqiuvalent of 'foldMap'.-  pxFoldMap :: Monoid m => (e -> m) -> Pixel cs e -> m+  -- | Right fold over all Pixel's components.+  foldrPx :: (e -> b -> b) -> b -> Pixel cs e -> b+  foldrPx f !z0 !xs = foldlPx f' id xs z0+      where f' k x !z = k $! f x z -  -- | Get a pure colour representation of a channel.-  csColour :: cs -> C.AlphaColour Double+  -- | Left strict fold over all Pixel's components.+  foldlPx :: (b -> e -> b) -> b -> Pixel cs e -> b+  foldlPx f !z0 !xs = foldrPx f' id xs z0+      where f' x k !z = k $! f z x++  foldl1Px :: (e -> e -> e) -> Pixel cs e -> e+  foldl1Px f !xs = fromMaybe (error "foldl1: empty Pixel")+                  (foldlPx mf Nothing xs)+      where+        mf m !y = Just (case m of+                           Nothing -> y+                           Just x  -> f x y)+  toListPx :: Pixel cs e -> [e]+  toListPx !px = foldr' f [] (enumFrom (toEnum 0))+    where f !cs !ls = getPxC px cs:ls+     -- | A color space that supports transparency.-class (ColorSpace (Opaque cs), ColorSpace cs) => Alpha cs where-  -- | An corresponding opaque version of this color space.+class (ColorSpace (Opaque cs) e, ColorSpace cs e) => AlphaSpace cs e where+  -- | A corresponding opaque version of this color space.   type Opaque cs    -- | Get an alpha channel of a transparant pixel. @@ -105,10 +122,7 @@   --   dropAlpha :: Pixel cs e -> Pixel (Opaque cs) e -  -- | Get a corresponding opaque channel type.-  opaque :: cs -> Opaque cs - -- | A class with a set of convenient functions that allow for changing precision of -- channels within pixels, while scaling the values to keep them in an appropriate range. --@@ -118,30 +132,36 @@ -- class Elevator e where -  toWord8 :: ColorSpace cs => Pixel cs e -> Pixel cs Word8+  -- | Values are scaled to @[0, 255]@ range.+  toWord8 :: e -> Word8 -  toWord16 :: ColorSpace cs => Pixel cs e -> Pixel cs Word16+  -- | Values are scaled to @[0, 65535]@ range.+  toWord16 :: e -> Word16 -  toWord32 :: ColorSpace cs => Pixel cs e -> Pixel cs Word32+  -- | Values are scaled to @[0, 4294967295]@ range.+  toWord32 :: e -> Word32 -  toWord64 :: ColorSpace cs => Pixel cs e -> Pixel cs Word64+  -- | Values are scaled to @[0, 18446744073709551615]@ range.+  toWord64 :: e -> Word64 -  toFloat :: ColorSpace cs => Pixel cs e -> Pixel cs Float+  -- | Values are scaled to @[0.0, 1.0]@ range.+  toFloat :: e -> Float -  toDouble :: ColorSpace cs => Pixel cs e -> Pixel cs Double+  -- | Values are scaled to @[0.0, 1.0]@ range.+  toDouble :: e -> Double -  fromDouble :: ColorSpace cs => Pixel cs Double -> Pixel cs e+  -- | Values are scaled from @[0.0, 1.0]@ range.+  fromDouble :: Double -> e   -- | Base array like representation for an image.-class (Show arr, ColorSpace cs, Num (Pixel cs e),-       Functor (Pixel cs), Applicative (Pixel cs), Foldable (Pixel cs),-       Num e, Typeable e, Elt arr cs e) =>+class (Show arr, ColorSpace cs e, Num (Pixel cs e),+       SuperClass arr cs e) =>       BaseArray arr cs e where    -- | Required array specific constraints for an array element.-  type Elt arr cs e :: Constraint-  type Elt arr cs e = ()+  type SuperClass arr cs e :: Constraint+  type SuperClass arr cs e = ()    -- | Underlying image representation.   data Image arr cs e@@ -169,6 +189,14 @@                -- argument and returns a pixel for that location.             -> Image arr cs e +  makeImageWindowed :: (Int, Int) -- ^ (@m@ rows, @n@ columns) - dimensions of a new image.+                    -> ((Int, Int), (Int, Int))+                    -> ((Int, Int) -> Pixel cs e)+                       -- ^ Function that generates inner pixels.+                    -> ((Int, Int) -> Pixel cs e)+                       -- ^ Function that generates border pixels+                    -> Image arr cs e+   -- | Create a singleton image, required for various operations on images with   -- a scalar.   singleton :: Pixel cs e -> Image arr cs e@@ -242,18 +270,32 @@   -- | Construct an image from a nested rectangular shaped list of pixels.   -- Length of an outer list will constitute @m@ rows, while the length of inner lists -   -- @n@ columns. All of the inner lists must be the same length and greater than @0@.+  --+  -- >>> fromLists [[PixelY (fromIntegral (i*j) / 60000) | j <- [1..300]] | i <- [1..200]]+  -- <Image VectorUnboxed Y (Double): 200x300>+  --+  -- <<images/grad_fromLists.png>>+  --   fromLists :: [[Pixel cs e]]             -> Image arr cs e    -- | Perform matrix multiplication on two images. Inner dimensions must agree.   (|*|) :: Image arr cs e -> Image arr cs e -> Image arr cs e -  -- | Undirected reduction of an image.+  -- | Undirected reduction of an image.    fold :: (Pixel cs e -> Pixel cs e -> Pixel cs e) -- ^ An associative folding function.        -> Pixel cs e -- ^ Initial element, that is neutral with respect to the folding function.        -> Image arr cs e -- ^ Source image.        -> Pixel cs e +  -- | Undirected reduction of an image with an index aware function.+  foldIx :: (Pixel cs e -> (Int, Int) -> Pixel cs e -> Pixel cs e)+            -- ^ Function that takes an accumulator, index, a pixel at that+            -- index and returns a new accumulator pixel.+         -> Pixel cs e -- ^ Initial element, that is neutral with respect to the folding function.+         -> Image arr cs e -- ^ Source image.+         -> Pixel cs e+   -- | Pixelwise equality function of two images. Images are   -- considered distinct if either images' dimensions or at least one pair of   -- corresponding pixels are not the same. Used in defining an in instance for@@ -268,7 +310,7 @@ -- | Array representation that is actually has real data stored in memory, hence -- allowing for image indexing, forcing pixels into computed state etc. class BaseArray arr cs e => MArray arr cs e  where-  data MImage st arr cs e+  data MImage s arr cs e    unsafeIndex :: Image arr cs e -> (Int, Int) -> Pixel cs e   @@ -314,7 +356,7 @@   foldM_ :: (Functor m, Monad m) => (a -> Pixel cs e -> m a) -> a -> Image arr cs e -> m ()    -- | Get dimensions of a mutable image.-  mdims :: MImage st arr cs e -> (Int, Int)+  mdims :: MImage s arr cs e -> (Int, Int)    -- | Yield a mutable copy of an image.   thaw :: (Functor m, PrimMonad m) =>@@ -461,105 +503,45 @@ {-# INLINE maybeIndex #-}  +-- | 2D to a flat vector index conversion.+--+-- __Note__: There is an implicit assumption that @j < n@+fromIx :: Int -- ^ @n@ columns+       -> (Int, Int) -- ^ @(i, j)@ row, column index+       -> Int -- ^ Flat vector index+fromIx !n !(i, j) = n * i + j+{-# INLINE fromIx #-} -instance ColorSpace cs => Functor (Pixel cs) where -  fmap = pxOp-  {-# INLINE fmap #-}-  -instance ColorSpace cs => Applicative (Pixel cs) where--  pure = fromChannel-  {-# INLINE pure #-}--  (<*>) = chApp-  {-# INLINE (<*>) #-}+-- | Flat vector to 2D index conversion.+toIx :: Int -- ^ @n@ columns+     -> Int -- ^ Flat vector index+     -> (Int, Int) -- ^ @(i, j)@ row, column index+toIx !n !k = divMod k n+{-# INLINE toIx #-}  -instance ColorSpace cs => Foldable (Pixel cs) where--  foldMap = pxFoldMap-  {-# INLINE foldMap #-}+checkDims :: String -> (Int, Int) -> (Int, Int)+checkDims err !ds@(m, n)+  | m <= 0 || n <= 0 = +    error $+    show err ++ ": Image dimensions are expected to be non-negative: " ++ show ds+  | otherwise = ds+{-# INLINE checkDims #-}  -instance (ColorSpace cs, Num e) => Num (Pixel cs e) where-  (+)         = liftA2 (+)-  {-# INLINE (+) #-}-  -  (-)         = liftA2 (-)-  {-# INLINE (-) #-}-  -  (*)         = liftA2 (*)-  {-# INLINE (*) #-}-  -  abs         = liftA abs-  {-# INLINE abs #-}-  -  signum      = liftA signum-  {-# INLINE signum #-}-  -  fromInteger = pure . fromInteger-  {-# INLINE fromInteger #-}-  --instance (ColorSpace cs, Fractional e) => Fractional (Pixel cs e) where-  (/)          = liftA2 (/)-  {-# INLINE (/) #-}+instance (Applicative (Pixel cs), Bounded e) => Bounded (Pixel cs e) where+  maxBound = pure maxBound+  {-# INLINE maxBound #-}   -  recip        = liftA recip-  {-# INLINE recip #-}--  fromRational = pure . fromRational-  {-# INLINE fromRational #-}+  minBound = pure minBound+  {-# INLINE minBound #-}  -instance (ColorSpace cs, Floating e) => Floating (Pixel cs e) where-  pi      = fromChannel pi-  {-# INLINE pi #-}--  exp     = liftA exp-  {-# INLINE exp #-}--  log     = liftA log-  {-# INLINE log #-}-  -  sin     = liftA sin-  {-# INLINE sin #-}-  -  cos     = liftA cos-  {-# INLINE cos #-}-  -  asin    = liftA asin-  {-# INLINE asin #-}-  -  atan    = liftA atan-  {-# INLINE atan #-}-  -  acos    = liftA acos-  {-# INLINE acos #-}-  -  sinh    = liftA sinh-  {-# INLINE sinh #-}-  -  cosh    = liftA cosh-  {-# INLINE cosh #-}-  -  asinh   = liftA asinh-  {-# INLINE asinh #-}-  -  atanh   = liftA atanh-  {-# INLINE atanh #-}-  -  acosh   = liftA acosh-  {-# INLINE acosh #-}-+instance (Foldable (Pixel cs), NFData e) => NFData (Pixel cs e) where -instance (ColorSpace cs, Bounded e) => Bounded (Pixel cs e) where-  maxBound = fromChannel maxBound-  {-# INLINE maxBound #-}-  -  minBound = fromChannel minBound-  {-# INLINE minBound #-}+  rnf = foldr' deepseq ()+  {-# INLINE rnf #-}   instance (Array arr cs e, Eq (Pixel cs e)) => Eq (Image arr cs e) where
src/Graphics/Image/Interface/Repa.hs view
@@ -1,4 +1,6 @@+{-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-} -- | -- Module      : Graphics.Image.Interface.Repa -- Copyright   : (c) Alexey Kuleshevich 2016@@ -8,50 +10,69 @@ -- Portability : non-portable -- module Graphics.Image.Interface.Repa (-  -- * Construction-  makeImageS, makeImageP, fromListsS, fromListsP,-  -- * Representation-  RS(..), RP(..),   -- * Conversion-  fromRepaArrayS, fromRepaArrayP, toRepaArray+  --fromRepaArrayS, fromRepaArrayP,+  toRepaArray,+  -- * Representation+  RSU(..), RPU(..), RSS(..), RPS(..)   ) where -import Graphics.Image.Interface hiding (makeImage, fromLists)-import qualified Graphics.Image.Interface as I (makeImage, fromLists)-import Graphics.Image.Interface.Repa.Internal+import Data.Array.Repa.Index+import qualified Data.Array.Repa as R +import Graphics.Image.Interface+import Graphics.Image.Interface.Repa.Generic+import Graphics.Image.Interface.Repa.Storable+import Graphics.Image.Interface.Repa.Unboxed --- | Create an image with sequential array representation.-makeImageS :: Array RS cs Double =>-             (Int, Int) -- ^ (@m@ rows, @n@ columns) - dimensions of a new image.-          -> ((Int, Int) -> Pixel cs Double)-             -- ^ A function that takes (@i@-th row, and @j@-th column) as an argument-             -- and returns a pixel for that location.-          -> Image RS cs Double-makeImageS = I.makeImage-{-# INLINE makeImageS #-} --- | Create an image with parallel array representation.-makeImageP :: Array RP cs Double =>-             (Int, Int) -- ^ (@m@ rows, @n@ columns) - dimensions of a new image.-          -> ((Int, Int) -> Pixel cs Double)-             -- ^ A function that takes (@i@-th row, and @j@-th column) as an argument-             -- and returns a pixel for that location.-          -> Image RP cs Double-makeImageP = I.makeImage-{-# INLINE makeImageP #-}  --- | Construct an image from a nested rectangular shaped list of pixels sequentially.-fromListsS-  :: Array RS cs e-  => [[Pixel cs e]] -> Image RS cs e-fromListsS = I.fromLists-{-# INLINE fromListsS #-} --- | Construct an image from a nested rectangular shaped list of pixels in parallel.-fromListsP-  :: Array RP cs e-  => [[Pixel cs e]] -> Image RP cs e-fromListsP = I.fromLists-{-# INLINE fromListsP #-}+-- | Makes a copy of an image into a Storable representation sequentially.+instance Exchangable RSU RSS where+  exchange _ (SUImage (SScalar px)) = SSImage (SScalar px)+  exchange _ (SUImage img)          = SSImage . compute . SDImage . getDelayedS $ img+  {-# INLINE exchange #-}+++-- | Makes a copy of an image into a Storable representation sequentially.+instance Exchangable RPU RPS where+  exchange _ (PUImage (PScalar px)) = PSImage (PScalar px)+  exchange _ (PUImage img)          = PSImage . compute . PDImage . getDelayedP $ img+  {-# INLINE exchange #-}+++-- | Makes a copy of an image into a Unboxed representation sequentially.+instance Exchangable RSS RSU where+  exchange _ (SSImage (SScalar px)) = SUImage (SScalar px)+  exchange _ (SSImage img)          = SUImage . compute . SDImage . getDelayedS $ img+  {-# INLINE exchange #-}+++-- | Makes a copy of an image into a Unboxed representation sequentially.+instance Exchangable RPS RPU where+  exchange _ (PSImage (PScalar px)) = PUImage (PScalar px)+  exchange _ (PSImage img)          = PUImage . compute . PDImage . getDelayedP $ img+  {-# INLINE exchange #-}++++-- -- | Create a sequential image from a 2D Repa delayed array.+-- fromRepaArrayS :: R.Array R.D DIM2 (Pixel cs e) -> Image RS cs e+-- fromRepaArrayS = SDImage+++-- -- | Create a parallel image from a 2D Repa delayed array.+-- fromRepaArrayP :: R.Array R.D DIM2 (Pixel cs e) -> Image RP cs e+-- fromRepaArrayP = PDImage++-- | Retrieve an underlying Repa array from an image.+toRepaArray+  :: (Array arr cs e, Array RSU cs e, Exchangable arr RSU)+  => Image arr cs e -> R.Array R.U DIM2 (Pixel cs e)+toRepaArray img =+  case exchange RSU img of+    (SUImage (STImage arr)) -> arr+    (SUImage (SDImage arr)) -> R.computeS arr+    (SUImage (SScalar px))  -> R.computeS $ R.fromFunction (Z :. 1 :. 1) $ const px
+ src/Graphics/Image/Interface/Repa/Generic.hs view
@@ -0,0 +1,494 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+#if __GLASGOW_HASKELL__ >= 800+    {-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+#endif+-- |+-- Module      : Graphics.Image.Interface.Repa.Generic+-- Copyright   : (c) Alexey Kuleshevich 2017+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>+-- Stability   : experimental+-- Portability : non-portable+--+module Graphics.Image.Interface.Repa.Generic where++import Prelude as P+import Data.Array.Repa.Index+import qualified Data.Array.Repa as R+import qualified Data.Array.Repa.Eval as R++import Graphics.Image.ColorSpace.Binary (Bit(..))+import Graphics.Image.Interface as I+import qualified Graphics.Image.Interface.Vector.Unboxed as IVU+import qualified Graphics.Image.Interface.Vector.Generic as IVG+import Graphics.Image.Interface.Repa.Helpers+++type family Repr arr :: *+++-- | Repa Array representation, which is computed in parallel.+data RP r = RP r++-- | Repa Array representation, which is computed sequentially. +data RS r = RS r++instance Show r => Show (RP r) where+  show (RP r) = "RepaParallel " ++ show r+  +instance Show r => Show (RS r) where+  show (RS r) = "RepaSequential " ++ show r+++-----------------------+-- Sequential Arrays --+-----------------------++instance SuperClass (RS r) cs e => BaseArray (RS r) cs e where+  type SuperClass (RS r) cs e =+    (Show r, ColorSpace cs e, Num (Pixel cs e), R.Elt (Pixel cs e), R.Elt e, +     R.Target (Repr (RS r)) (Pixel cs e), R.Source (Repr (RS r)) (Pixel cs e),+     IVU.Unbox e, IVU.Unbox (Components cs e), +     BaseArray (IVG.V r) cs e, Repr (RP r) ~ Repr (RS r))+  +  data Image (RS r) cs e = SScalar !(Pixel cs e)+                         | STImage !(R.Array (Repr (RS r)) R.DIM2 (Pixel cs e))+                         | SDImage !(R.Array R.D R.DIM2 (Pixel cs e))+                       +  dims (SScalar _                          ) = (1, 1)+  dims (STImage (R.extent -> (Z :. m :. n))) = (m, n)+  dims (SDImage (R.extent -> (Z :. m :. n))) = (m, n)+  {-# INLINE dims #-}+++instance (BaseArray (RS r) cs e) => Array (RS r) cs e where++  type Manifest (RS r) = Manifest (IVG.V r)+  +  makeImage !(checkDims "RS.makeImage" -> (m, n)) f =+    SDImage $ R.fromFunction (Z :. m :. n) (f . sh2ix)+  {-# INLINE makeImage #-}+  +  makeImageWindowed !(checkDims "RS.makeImage" -> (m, n)) !window getWindowPx getBorderPx  =+    SDImage $ R.delay $ makeWindowed (Z :. m :. n) window+    (R.fromFunction (Z :. m :. n) (getWindowPx . sh2ix))+     (R.fromFunction (Z :. m :. n) (getBorderPx . sh2ix))+    +  singleton = SScalar+  {-# INLINE singleton #-}++  index00 (SScalar px)  = px+  index00 (STImage arr) = R.index arr (Z :. 0 :. 0)+  index00 (SDImage arr) = R.index arr (Z :. 0 :. 0)+  {-# INLINE index00 #-}++  map f (SScalar px)  = SScalar (f px)+  map f (STImage arr) = SDImage (R.map f arr)+  map f (SDImage arr) = SDImage (R.map f arr)+  {-# INLINE map #-}++  imap f (SScalar px)  = SScalar (f (0, 0) px)+  imap f (STImage arr) = SDImage (imapR f arr)+  imap f (SDImage arr) = SDImage (imapR f arr)+  {-# INLINE imap #-}++  zipWith f (SScalar px1) (SScalar px2) = SScalar (f px1 px2)+  zipWith f (SScalar px1) !img2         = I.map (f px1) img2+  zipWith f !img1         (SScalar px2) = I.map (`f` px2) img1+  zipWith f !img1         !img2         =+    SDImage (R.zipWith f (getDelayedS img1) (getDelayedS img2))+  {-# INLINE zipWith #-}++  izipWith f (SScalar px1) (SScalar px2) = SScalar (f (0, 0) px1 px2)+  izipWith f (SScalar px1) !img2         = imap (`f` px1) img2+  izipWith f !img1         (SScalar px2) = imap (\ !ix !px -> f ix px px2) img1+  izipWith f !img1         !img2         =+    SDImage (izipWithR f (getDelayedS img1) (getDelayedS img2))+  {-# INLINE izipWith #-}+  +  traverse !img getNewDims getNewPx =+    SDImage (traverseR (getDelayedS img) getNewDims getNewPx)+  {-# INLINE traverse #-}++  traverse2 !img1 !img2 getNewDims getNewPx =+    SDImage (traverse2R (getDelayedS img1) (getDelayedS img2) getNewDims getNewPx)+  {-# INLINE traverse2 #-}++  transpose (SDImage arr) = SDImage (R.transpose arr)+  transpose (STImage arr) = SDImage (R.transpose arr)+  transpose !img          = img+  {-# INLINE transpose #-}++  backpermute !newDims g !img = SDImage (backpermuteR (getDelayedS img) newDims g)+  {-# INLINE backpermute #-}++  fromLists = STImage . fromListsR+  {-# INLINE fromLists #-}++  fold f !px0 (SDImage arr) = R.foldAllS f px0 arr+  fold f !px0 (STImage arr) = R.foldAllS f px0 arr+  fold f !px0 (SScalar px)  = f px px0+  {-# INLINE fold #-}++  foldIx f !px0 (SDImage arr) = foldIxS f px0 arr+  foldIx f !px0 (STImage arr) = foldIxS f px0 arr+  foldIx f !px0 (SScalar px)  = f px0 (0, 0) px+  {-# INLINE foldIx #-}++  eq (SScalar px1) (SScalar px2) = px1 == px2+  eq !img1 !img2 = R.equalsS (getDelayedS img1) (getDelayedS img2)+  {-# INLINE eq #-}++  compute !img@(SScalar _) = img+  compute !img@(STImage _) = img+  compute (SDImage arr)    = STImage (R.computeS arr)+  {-# INLINE compute #-}++  (|*|) img1@(STImage arr1) img2@(STImage arr2) =+     SDImage (multR (show img1 ++ " X " ++ show img2) arr1 arr2)+  (|*|) img1@(SDImage _) !img2            = compute img1 |*| img2+  (|*|) !img1            img2@(SDImage _) = img1 |*| compute img2+  (|*|) (SScalar px1)    !img2            = STImage (singletonR px1) |*| img2+  (|*|) !img1            (SScalar px2)    = img1 |*| STImage (singletonR px2)+  {-# INLINE (|*|) #-}++  toManifest _ = error $ "RS.toManifest: Cannot convert generic Repa " +++                         "representation to a generic Vector."+  {-# INLINE toManifest #-}+++---------------------+-- Parallel Arrays --+---------------------++++instance SuperClass (RP r) cs e => BaseArray (RP r) cs e where+  type SuperClass (RP r) cs e = (+    Show r, ColorSpace cs e, Num (Pixel cs e),+    R.Target (Repr (RP r)) (Pixel cs e), R.Source (Repr (RP r)) (Pixel cs e),+    BaseArray (IVG.V r) cs e, Repr (RP r) ~ Repr (RS r),+    IVU.Unbox e, IVU.Unbox (Components cs e), R.Elt e, R.Elt (Pixel cs e))+  +  data Image (RP r) cs e = PScalar !(Pixel cs e)+                         | PTImage !(R.Array (Repr (RP r)) R.DIM2 (Pixel cs e))+                         | PDImage !(R.Array R.D R.DIM2 (Pixel cs e))+                       +  dims (PScalar _                          ) = (1, 1)+  dims (PTImage (R.extent -> (Z :. m :. n))) = (m, n)+  dims (PDImage (R.extent -> (Z :. m :. n))) = (m, n)+  {-# INLINE dims #-}+++instance (BaseArray (RP r) cs e) => Array (RP r) cs e where++  type Manifest (RP r) = Manifest (IVG.V r)+  +  makeImage !(checkDims "RP.makeImage" -> (m, n)) f =+    PDImage $ R.fromFunction (Z :. m :. n) (f . sh2ix)+  {-# INLINE makeImage #-}+  +  makeImageWindowed !(checkDims "RP.makeImage" -> (m, n)) !window getWindowPx getBorderPx  =+    PDImage $ R.delay $ makeWindowed (Z :. m :. n) window+    (R.fromFunction (Z :. m :. n) (getWindowPx . sh2ix))+     (R.fromFunction (Z :. m :. n) (getBorderPx . sh2ix))+    +  singleton = PScalar+  {-# INLINE singleton #-}++  index00 (PScalar px)  = px+  index00 (PTImage arr) = R.index arr (Z :. 0 :. 0)+  index00 (PDImage arr) = R.index arr (Z :. 0 :. 0)+  {-# INLINE index00 #-}++  map f (PScalar px)  = PScalar (f px)+  map f (PTImage arr) = PDImage (R.map f arr)+  map f (PDImage arr) = PDImage (R.map f arr)+  {-# INLINE map #-}++  imap f (PScalar px)  = PScalar (f (0, 0) px)+  imap f (PTImage arr) = PDImage (imapR f arr)+  imap f (PDImage arr) = PDImage (imapR f arr)+  {-# INLINE imap #-}++  zipWith f (PScalar px1) (PScalar px2) = PScalar (f px1 px2)+  zipWith f (PScalar px1) !img2         = I.map (f px1) img2+  zipWith f !img1         (PScalar px2) = I.map (`f` px2) img1+  zipWith f !img1         !img2         =+    PDImage (R.zipWith f (getDelayedP img1) (getDelayedP img2))+  {-# INLINE zipWith #-}++  izipWith f (PScalar px1) (PScalar px2) = PScalar (f (0, 0) px1 px2)+  izipWith f (PScalar px1) !img2         = imap (`f` px1) img2+  izipWith f !img1         (PScalar px2) = imap (\ !ix !px -> f ix px px2) img1+  izipWith f !img1         !img2         =+    PDImage (izipWithR f (getDelayedP img1) (getDelayedP img2))+  {-# INLINE izipWith #-}+  +  traverse !img getNewDims getNewPx =+    PDImage (traverseR (getDelayedP img) getNewDims getNewPx)+  {-# INLINE traverse #-}++  traverse2 !img1 !img2 getNewDims getNewPx =+    PDImage (traverse2R (getDelayedP img1) (getDelayedP img2) getNewDims getNewPx)+  {-# INLINE traverse2 #-}++  transpose (PDImage arr) = PDImage (R.transpose arr)+  transpose (PTImage arr) = PDImage (R.transpose arr)+  transpose !img          = img+  {-# INLINE transpose #-}++  backpermute !newDims g !img = PDImage (backpermuteR (getDelayedP img) newDims g)+  {-# INLINE backpermute #-}++  fromLists = PTImage . fromListsR+  {-# INLINE fromLists #-}++  fold f !px0 (PScalar px) = f px0 px+  fold f !px0 img =+    case R.foldAllP f px0 (getDelayedP img) of+      Just e  -> e+      Nothing -> error $ "RP.fold: impossible happened."+  {-# INLINE fold #-}++  foldIx f !px0 (PScalar px) = f px0 (0, 0) px+  foldIx f !px0 img =+    case foldIxPUnboxed f px0 (getDelayedP img) of+      Just e  -> e+      Nothing -> error $ "RP.foldIx: impossible happened."+  {-# INLINE foldIx #-}+++  eq (PScalar px1) (PScalar px2) = px1 == px2+  eq !img1 !img2 =+    case R.equalsP (getDelayedP img1) (getDelayedP img2) of+      Just e  -> e+      Nothing -> error $ "RP.eq: impossible happened."+  {-# INLINE eq #-}++  compute !img@(PScalar _) = img+  compute !img@(PTImage _) = img+  compute (PDImage arr)    = arrManifest `R.deepSeqArray` PTImage arrManifest+     where arrManifest = R.suspendedComputeP arr+  {-# INLINE compute #-}++  (|*|) img1@(PTImage arr1) img2@(PTImage arr2) =+     PDImage (multR (show img1 ++ " X " ++ show img2) arr1 arr2)+  (|*|) img1@(PDImage _) !img2            = compute img1 |*| img2+  (|*|) !img1            img2@(PDImage _) = img1 |*| compute img2+  (|*|) (PScalar px1)    !img2            = PTImage (singletonR px1) |*| img2+  (|*|) !img1            (PScalar px2)    = img1 |*| PTImage (singletonR px2)+  {-# INLINE (|*|) #-}++  toManifest _ = error $ "RP.toManifest: Cannot convert generic Repa " +++                         "representation to a generic Vector."+  {-# INLINE toManifest #-}++++----------------------+-- Helper functions --+----------------------++sh2ix :: DIM2 -> (Int, Int)+sh2ix (Z :. i :. j) = (i, j)+{-# INLINE sh2ix #-}++ix2sh :: (Int, Int) -> DIM2+ix2sh !(i, j) = Z :. i :. j +{-# INLINE ix2sh #-}+++toRS :: Repr (RP r) ~ Repr (RS r) => Image (RP r) cs e -> Image (RS r) cs e+toRS (PScalar px)  = SScalar px+toRS (PDImage img) = SDImage img+toRS (PTImage img) = STImage img++toRP :: Repr (RP r) ~ Repr (RS r) => Image (RS r) cs e -> Image (RP r) cs e+toRP (SScalar px)  = PScalar px+toRP (SDImage img) = PDImage img+toRP (STImage img) = PTImage img+++imapR+  :: R.Source r2 b =>+     ((Int, Int) -> b -> c) -> R.Array r2 DIM2 b -> R.Array R.D DIM2 c+imapR f !arr = R.zipWith f (R.fromFunction (R.extent arr) sh2ix) arr+++-- | Combine two arrays, element-wise, with index aware operator. If the extent of+-- the two array arguments differ, then the resulting array's extent is their+-- intersection.+izipWithR+  :: (R.Source r2 t1, R.Source r1 t)+  => ((Int, Int) -> t -> t1 -> c)+  -> R.Array r1 DIM2 t+  -> R.Array r2 DIM2 t1+  -> R.Array R.D DIM2 c+izipWithR f !arr1 !arr2 =+  (R.traverse2 arr1 arr2 getNewDims getNewPx) where+    getNewPx !getPx1 !getPx2 !sh = f (sh2ix sh) (getPx1 sh) (getPx2 sh)+    getNewDims (Z :. m1 :. n1) (Z :. m2 :. n2) = Z :. min m1 m2 :. min n1 n2+    {-# INLINE getNewPx #-}+{-# INLINE izipWithR #-}+++traverseR+  :: R.Source r c+  => R.Array r DIM2 c+  -> ((Int, Int) -> (Int, Int))+  -> (((Int, Int) -> c) -> (Int, Int) -> b)+  -> R.Array R.D DIM2 b+traverseR !arr getNewDims getNewPx =+  R.traverse arr (ix2sh . checkDims "traverseR" . getNewDims . sh2ix) getNewE+  where+    getNewE getPx = getNewPx (getPx . ix2sh) . sh2ix+    {-# INLINE getNewE #-}+{-# INLINE traverseR #-}++traverse2R+  :: (R.Source r2 c1, R.Source r1 c)+  => R.Array r1 DIM2 c+  -> R.Array r2 DIM2 c1+  -> ((Int, Int) -> (Int, Int) -> (Int, Int))+  -> (((Int, Int) -> c) -> ((Int, Int) -> c1) -> (Int, Int) -> c2)+  -> R.Array R.D DIM2 c2+traverse2R !arr1 !arr2 getNewDims getNewPx =+  R.traverse2 arr1 arr2 getNewSh getNewE+  where getNewE getPx1 getPx2 = getNewPx (getPx1 . ix2sh) (getPx2 . ix2sh) . sh2ix+        {-# INLINE getNewE #-}+        getNewSh !sh1 !sh2 =+          ix2sh . checkDims "traverse2R" $ getNewDims (sh2ix sh1) (sh2ix sh2)+        {-# INLINE getNewSh #-}+{-# INLINE traverse2R #-}++backpermuteR+  :: R.Source r e+  => R.Array r DIM2 e+  -> (Int, Int)+  -> ((Int, Int) -> (Int, Int))+  -> R.Array R.D DIM2 e+backpermuteR !arr newDims g =+  R.backpermute+    (ix2sh (checkDims "backpermuteR" newDims))+    (ix2sh . g . sh2ix)+    arr+{-# INLINE backpermuteR #-}+++fromListsR :: (R.Target r e) => [[e]] -> R.Array r DIM2 e+fromListsR ls =+  if all (== n) (P.map length ls)+    then R.fromList (Z :. m :. n) . concat $ ls+    else error "fromListsR: Inner lists do not all have an equal length."+  where+    !(m, n) = checkDims "fromListsR" (length ls, length $ head ls)+{-# INLINE fromListsR #-}++++multR+  :: (ColorSpace cs e, IVU.Unbox (Components cs e), Num (Pixel cs e), R.Elt (Pixel cs e),+      R.Target r (Pixel cs e), R.Source r (Pixel cs e))+  => String -> R.Array r DIM2 (Pixel cs e) -> R.Array r DIM2 (Pixel cs e) -> R.Array R.D DIM2 (Pixel cs e)+multR errMsg !arr1 !arr2 =+  if n1 /= m2+    then error $+         "Inner dimensions of multiplied images must be the same, but received: " ++ errMsg+    else R.fromFunction (Z :. m1 :. n2) $ getPx+  where+    (Z :. m1 :. n1) = R.extent arr1+    (Z :. m2 :. n2) = R.extent arr2+    getPx (Z :. i :. j) =+      R.sumAllS+        (R.slice arr1 (R.Any :. (i :: Int) :. R.All) R.*^+         R.slice arr2 (R.Any :. (j :: Int)))+    {-# INLINE getPx #-}+{-# INLINE multR #-}+++singletonR :: (IVU.Unbox a, R.Target r a) => a -> R.Array r DIM2 a+singletonR !px = R.computeS $ R.fromFunction (Z :. 1 :. 1) $ const px+++getDelayedS :: Array (RS r) cs e => Image (RS r) cs e -> R.Array R.D DIM2 (Pixel cs e)+getDelayedS (STImage arr) = R.delay arr+getDelayedS (SDImage arr) = arr+getDelayedS (SScalar px)  = R.fromFunction (Z :. 1 :. 1) (const px)+{-# INLINE getDelayedS #-}++getDelayedP :: Array (RP r) cs e => Image (RP r) cs e -> R.Array R.D DIM2 (Pixel cs e)+getDelayedP (PTImage arr) = R.delay arr+getDelayedP (PDImage arr) = arr+getDelayedP (PScalar px)  = R.fromFunction (Z :. 1 :. 1) (const px)+{-# INLINE getDelayedP #-}+++instance R.Elt Bit where+  touch (Bit w) = R.touch w+  {-# INLINE touch #-}+  +  zero     = 0+  {-# INLINE zero #-}+  +  one      = 1+  {-# INLINE one #-}+++instance (ColorSpace cs e, R.Elt e, Num (Pixel cs e)) => R.Elt (Pixel cs e) where+  touch !px = P.mapM_ (R.touch . getPxC px) (enumFrom (toEnum 0)) +  {-# INLINE touch #-}+  +  zero     = 0+  {-# INLINE zero #-}+  +  one      = 1+  {-# INLINE one #-}+++addIxArr+  :: R.Source r2 b =>+     R.Array r2 DIM2 b -> R.Array R.D DIM2 ((Int, Int), b)+addIxArr !arr = R.zipWith (,) arrIx arr+  where+    !arrIx = R.fromFunction (R.extent arr) sh2ix+{-# INLINE addIxArr #-}+++foldIxS+  :: (R.Elt b, R.Source r2 b, IVU.Unbox b) =>+     (b -> (Int, Int) -> b -> b) -> b -> R.Array r2 DIM2 b -> b+foldIxS f !acc !arr = snd $ R.foldAllS g ((-1, 0), acc) arr'+  where+    !arr' = addIxArr arr+    g (accIx@(-1, _), acc') !(ix, px) = (accIx, f acc' ix px)+    g !(ix, px) (accIx@(-1, _), acc') = (accIx, f acc' ix px)+    g (acc1Ix, _) (acc2Ix, _) =+      error $ "foldIxS: Impossible happened. Received: " ++ show acc1Ix ++ " " ++ show acc2Ix+    {-# INLINE g #-}+{-# INLINE foldIxS #-}+++foldIxPUnboxed+  :: (R.Source r2 b, IVU.Unbox b, R.Elt b, Functor m, Monad m)+  => (b -> (Int, Int) -> b -> b) -> b -> R.Array r2 DIM2 b -> m b+foldIxPUnboxed f !acc !arr = snd <$> R.foldAllP g ((-1, 0), acc) arr'+  where+    !arr' = addIxArr arr+    g (accIx@(-1, _), acc') !(ix, px) = (accIx, f acc' ix px)+    g !(ix, px) (accIx@(-1, _), acc') = (accIx, f acc' ix px)+    g (acc1Ix, _) (acc2Ix, _) =+      error $ "foldIxPUnboxed: Impossible happened. Received: " ++ show acc1Ix ++ " " ++ show acc2Ix+    {-# INLINE g #-}+{-# INLINE foldIxPUnboxed #-}+
+ src/Graphics/Image/Interface/Repa/Helpers.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+module Graphics.Image.Interface.Repa.Helpers where++import Data.Array.Repa+import Data.Array.Repa.Repr.Partitioned+import Data.Array.Repa.Repr.Undefined++-- | Make a 2D windowed array from two others, one to produce the elements in+--   the internal region, and one to produce elements in the border region. The+--   two arrays must have the same extent.+--+makeWindowed+        :: (Source r1 a, Source r2 a)+        => DIM2                 -- ^ Extent of array.+        -> ((Int, Int), (Int, Int))  -- ^ Window points.+        -> Array r1 DIM2 a      -- ^ Array for internal elements.+        -> Array r2 DIM2 a      -- ^ Array for border elements.+        -> Array (P r1 (P r2 (P r2 (P r2 (P r2 X))))) DIM2 a+makeWindowed sh@(_ :. m :. n) !((it, jt), (ib, jb)) arrWindow arrBorder =+  checkDims `seq`+  let inInternal (Z :. i :. j) = i >= it && i < ib && j >= jt && j < jb+      {-# INLINE inInternal #-}+      inBorder = not . inInternal+      {-# INLINE inBorder #-}+  in APart sh (Range (Z :. it :. jt) (Z :. (ib - it) :. (jb - jt)) inInternal) arrWindow $+     APart sh (Range (Z :. 0 :.  0 ) (Z :. it        :. n        ) inBorder  ) arrBorder $+     APart sh (Range (Z :. it :. 0 ) (Z :. (ib - it) :. jt       ) inBorder  ) arrBorder $+     APart sh (Range (Z :. it :. jb) (Z :. (ib - it) :. (n - jb) ) inBorder  ) arrBorder $+     APart sh (Range (Z :. ib :. 0 ) (Z :. (m - ib)  :. n        ) inBorder  ) arrBorder $+     AUndefined sh+  where+    checkDims =+      if extent arrWindow == extent arrBorder+        then ()+        else error+               "makeWindowed: internal and border arrays have different extents"+    {-# NOINLINE checkDims #-}+{-# INLINE makeWindowed #-}
− src/Graphics/Image/Interface/Repa/Internal.hs
@@ -1,490 +0,0 @@-{-# OPTIONS -fno-warn-orphans #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module      : Graphics.Image.Interface.Repa.Internal--- Copyright   : (c) Alexey Kuleshevich 2016--- License     : BSD3--- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>--- Stability   : experimental--- Portability : non-portable----module Graphics.Image.Interface.Repa.Internal (-  RP(..), RS(..),-  fromRepaArrayS, fromRepaArrayP, toRepaArray-  ) where--#if MIN_VERSION_base(4,8,0)-import Prelude hiding (map, zipWith, foldl, foldr, mapM, mapM_, read, traverse)-#else-import Prelude hiding (map, zipWith, foldl, foldr, mapM, mapM_, read)-#endif-import qualified Prelude as P (map, mapM_)-import Graphics.Image.Interface-import Graphics.Image.ColorSpace.Binary (Bit(..))-import Graphics.Image.Interface.Vector.Unboxed-       (VU(..), fromUnboxedVector, toUnboxedVector, checkDims)-import Data.Array.Repa.Repr.Unboxed (Unbox)-import qualified Data.Vector.Unboxed as V (singleton)--import Data.Typeable (Typeable)-import Data.Array.Repa.Index-import qualified Data.Array.Repa as R -import qualified Data.Array.Repa.Eval as R (Elt(..), suspendedComputeP)----- | Repa 'U'nboxed Array representation, which is computed in parallel.-data RP = RP---- | Repa 'U'nboxed Array representation, which is computed sequentially. -data RS = RS--instance Show RP where-  show _ = "RepaParallel"-  -instance Show RS where-  show _ = "RepaSequential"----instance Elt RS cs e => BaseArray RS cs e where-  type Elt RS cs e = (ColorSpace cs, -                      R.Elt e, Unbox e, Num e, Typeable e,-                      R.Elt (PixelElt cs e), Unbox (PixelElt cs e),-                      R.Elt (Pixel cs e), Unbox (Pixel cs e))-  -  data Image RS cs e = SScalar !(Pixel cs e)-                     | SUImage !(R.Array R.U R.DIM2 (Pixel cs e))-                     | SDImage !(R.Array R.D R.DIM2 (Pixel cs e))-                       -  dims (SScalar _                          ) = (1, 1)-  dims (SUImage (R.extent -> (Z :. m :. n))) = (m, n)-  dims (SDImage (R.extent -> (Z :. m :. n))) = (m, n)-  {-# INLINE dims #-}---instance (BaseArray RS cs e) => Array RS cs e where--  type Manifest RS = VU-  -  makeImage !(checkDims "RS.makeImage" -> (m, n)) !f =-    SDImage $ R.fromFunction (Z :. m :. n) (f . sh2dims)-  {-# INLINE makeImage #-}-  -  singleton = SScalar-  {-# INLINE singleton #-}--  index00 (SScalar px)  = px-  index00 (SUImage arr) = R.index arr (Z :. 0 :. 0)-  index00 (SDImage arr) = R.index arr (Z :. 0 :. 0)-  {-# INLINE index00 #-}--  map !f (SScalar px)  = SScalar (f px)-  map !f (SUImage arr) = SDImage (R.map f arr)-  map !f (SDImage arr) = SDImage (R.map f arr)-  {-# INLINE map #-}--  imap !f (SScalar px)  = SScalar (f (0, 0) px)-  imap !f (SUImage arr) = SDImage (imapR f arr)-  imap !f (SDImage arr) = SDImage (imapR f arr)-  {-# INLINE imap #-}--  zipWith f (SScalar px1)  (SScalar px2)  = SScalar (f px1 px2)-  zipWith f (SScalar px1)  img2           = map (f px1) img2-  zipWith f img1           (SScalar px2)  = map (`f` px2) img1-  zipWith f img1           img2           =-    SDImage (R.zipWith f (getDelayedS img1) (getDelayedS img2))-  {-# INLINE zipWith #-}--  izipWith f (SScalar px1)  (SScalar px2)  = SScalar (f (0, 0) px1 px2)-  izipWith f (SScalar px1)  img2           = imap (`f` px1) img2-  izipWith f img1           (SScalar px2)  = imap (\ !ix !px -> f ix px px2) img1-  izipWith f img1           img2           =-    SDImage (izipWithR f (getDelayedS img1) (getDelayedS img2))-  {-# INLINE izipWith #-}-  -  -- traverse (SScalar px) getNewDims getNewPx =-  --   makeImage (getNewDims (1, 1)) (getNewPx (const px))-  traverse img          getNewDims getNewPx =-    SDImage (traverseR (getDelayedS img) getNewDims getNewPx)-  {-# INLINE traverse #-}--  -- traverse2 (SScalar px1) (SScalar px2) getNewDims getNewPx =-  --   makeImage (getNewDims (1, 1) (1, 1)) (getNewPx (const px1) (const px2))-  traverse2 img1 img2 getNewDims getNewPx =-    SDImage (traverse2R (getDelayedS img1) (getDelayedS img2) getNewDims getNewPx)-  {-# INLINE traverse2 #-}--  transpose (SDImage arr) = SDImage (R.transpose arr)-  transpose (SUImage arr) = SDImage (R.transpose arr)-  transpose !img          = img-  {-# INLINE transpose #-}--  -- backpermute !newDims _ (SScalar px) =-  --   SDImage $ R.fromFunction (dims2sh $ checkDims "RS.backpermute" newDims) (const px)-  backpermute !newDims g !img = SDImage (backpermuteR (getDelayedS img) newDims g)-  {-# INLINE backpermute #-}--  fromLists = SUImage . fromListsR-  {-# INLINE fromLists #-}--  fold f !px0 (SDImage arr) = R.foldAllS f px0 arr-  fold f !px0 (SUImage arr) = R.foldAllS f px0 arr-  fold f !px0 (SScalar px)  = f px0 px-  {-# INLINE fold #-}--  eq (SScalar px1) (SScalar px2) = px1 == px2-  eq img1 img2 = R.equalsS (getDelayedS img1) (getDelayedS img2)-  {-# INLINE eq #-}--  compute img@(SScalar _) = img-  compute img@(SUImage _) = img-  compute (SDImage arr)   = SUImage $ R.computeS arr-  {-# INLINE compute #-}--  (SUImage arr1)   |*| (SUImage arr2)   = SDImage (multR arr1 arr2)-  img1@(SDImage _) |*| img2             = compute img1 |*| img2-  img1             |*| img2@(SDImage _) = img1 |*| compute img2-  (SScalar px1)    |*| img2             = SUImage (singletonR px1) |*| img2-  img1             |*| (SScalar px2)    = img1 |*| SUImage (singletonR px2)-  {-# INLINE (|*|) #-}--  toManifest img@(SUImage arr) = fromUnboxedVector (dims img) (R.toUnboxed arr)-  toManifest (SScalar px)      = singleton px-  toManifest img               = toManifest (compute img)-  {-# INLINE toManifest #-}-------------------------- Parallel Arrays --------------------------instance Elt RP cs e => BaseArray RP cs e where-  type Elt RP cs e = (ColorSpace cs, -                      R.Elt e, Unbox e, Num e, Typeable e,-                      R.Elt (PixelElt cs e), Unbox (PixelElt cs e),-                      R.Elt (Pixel cs e), Unbox (Pixel cs e))-  -  data Image RP cs e = PScalar !(Pixel cs e)-                     | PUImage !(R.Array R.U R.DIM2 (Pixel cs e))-                     | PDImage !(R.Array R.D R.DIM2 (Pixel cs e))-                       -  dims (PScalar _                          ) = (1, 1)-  dims (PUImage (R.extent -> (Z :. m :. n))) = (m, n)-  dims (PDImage (R.extent -> (Z :. m :. n))) = (m, n)-  {-# INLINE dims #-}---instance (BaseArray RP cs e) => Array RP cs e where--  type Manifest RP = VU-  -  makeImage !(checkDims "RP.makeImage" -> (m, n)) !f =-    PDImage $ R.fromFunction (Z :. m :. n) (f . sh2dims)-  {-# INLINE makeImage #-}-  -  singleton = PScalar-  {-# INLINE singleton #-}--  index00 (PScalar px)  = px-  index00 (PUImage arr) = R.index arr (Z :. 0 :. 0)-  index00 (PDImage arr) = R.index arr (Z :. 0 :. 0)-  {-# INLINE index00 #-}--  map !f (PScalar px)  = PScalar (f px)-  map !f (PUImage arr) = PDImage (R.map f arr)-  map !f (PDImage arr) = PDImage (R.map f arr)-  {-# INLINE map #-}--  imap !f (PScalar px)  = PScalar (f (0, 0) px)-  imap !f (PUImage arr) = PDImage (imapR f arr)-  imap !f (PDImage arr) = PDImage (imapR f arr)-  {-# INLINE imap #-}--  zipWith f (PScalar px1)  (PScalar px2)  = PScalar (f px1 px2)-  zipWith f (PScalar px1)  img2           = map (f px1) img2-  zipWith f img1           (PScalar px2)  = map (`f` px2) img1-  zipWith f img1           img2           =-    PDImage (R.zipWith f (getDelayedP img1) (getDelayedP img2))-  {-# INLINE zipWith #-}--  izipWith f (PScalar px1)  (PScalar px2)  = PScalar (f (0, 0) px1 px2)-  izipWith f (PScalar px1)  img2           = imap (`f` px1) img2-  izipWith f img1           (PScalar px2)  = imap (\ !ix !px -> f ix px px2) img1-  izipWith f img1           img2           =-    PDImage (izipWithR f (getDelayedP img1) (getDelayedP img2))-  {-# INLINE izipWith #-}-  -  -- traverse (PScalar px) getNewDims getNewPx =-  --   makeImage (getNewDims (1, 1)) (getNewPx (const px))-  traverse img          getNewDims getNewPx =-    PDImage (traverseR (getDelayedP img) getNewDims getNewPx)-  {-# INLINE traverse #-}--  -- traverse2 (PScalar px1) (PScalar px2) getNewDims getNewPx =-  --   makeImage (getNewDims (1, 1) (1, 1)) (getNewPx (const px1) (const px2))-  traverse2 img1 img2 getNewDims getNewPx =-    PDImage (traverse2R (getDelayedP img1) (getDelayedP img2) getNewDims getNewPx)-  {-# INLINE traverse2 #-}--  transpose (PDImage arr) = PDImage (R.transpose arr)-  transpose (PUImage arr) = PDImage (R.transpose arr)-  transpose !img          = img-  {-# INLINE transpose #-}--  -- backpermute !newDims _ (PScalar px) =-  --   PDImage $ R.fromFunction (dims2sh $ checkDims "RS.backpermute" newDims) (const px)-  backpermute !newDims g !img = PDImage (backpermuteR (getDelayedP img) newDims g)-  {-# INLINE backpermute #-}--  fromLists = PUImage . fromListsR-  {-# INLINE fromLists #-}--  fold f !px0 (PDImage arr) = head $ R.foldAllP f px0 arr-  fold f !px0 (PUImage arr) = head $ R.foldAllP f px0 arr-  fold f !px0 (PScalar px)  = f px0 px-  {-# INLINE fold #-}--  eq (PScalar px1) (PScalar px2) = px1 == px2-  eq img1 img2 = R.equalsS (getDelayedP img1) (getDelayedP img2)-  {-# INLINE eq #-}--  compute img@(PScalar _) = img-  compute img@(PUImage _) = img-  compute (PDImage arr)   = arrU `R.deepSeqArray` PUImage arrU-    where arrU = R.suspendedComputeP arr-  {-# INLINE compute #-}--  (PUImage arr1)   |*| (PUImage arr2)   = PDImage (multR arr1 arr2)-  img1@(PDImage _) |*| img2             = compute img1 |*| img2-  img1             |*| img2@(PDImage _) = img1 |*| compute img2-  (PScalar px1)    |*| img2             = PUImage (singletonR px1) |*| img2-  img1             |*| (PScalar px2)    = img1 |*| PUImage (singletonR px2)-  {-# INLINE (|*|) #-}--  toManifest img@(PUImage arr) = fromUnboxedVector (dims img) (R.toUnboxed arr)-  toManifest (PScalar px)      = singleton px-  toManifest img               = toManifest (compute img)-  {-# INLINE toManifest #-}---------------------------- Helper functions ---------------------------sh2dims :: DIM2 -> (Int, Int)-sh2dims (Z :. i :. j) = (i, j)-{-# INLINE sh2dims #-}--dims2sh :: (Int, Int) -> DIM2-dims2sh !(i, j) = Z :. i :. j -{-# INLINE dims2sh #-}---imapR-  :: R.Source r2 b =>-     ((Int, Int) -> b -> c) -> R.Array r2 DIM2 b -> R.Array R.D DIM2 c-imapR f arr = R.zipWith f (R.fromFunction (R.extent arr) sh2dims) arr----- | Combine two arrays, element-wise, with index aware operator. If the extent of--- the two array arguments differ, then the resulting array's extent is their--- intersection.-izipWithR-  :: (R.Source r2 t1, R.Source r1 t)-  => ((Int, Int) -> t -> t1 -> c)-  -> R.Array r1 DIM2 t-  -> R.Array r2 DIM2 t1-  -> R.Array R.D DIM2 c-izipWithR f arr1 arr2 =-  (R.traverse2 arr1 arr2 getNewDims getNewPx) where-    getNewPx !getPx1 !getPx2 !sh = f (sh2dims sh) (getPx1 sh) (getPx2 sh)-    getNewDims (Z :. m1 :. n1) (Z :. m2 :. n2) = Z :. min m1 m2 :. min n1 n2-    {-# INLINE getNewPx #-}-{-# INLINE izipWithR #-}---traverseR-  :: R.Source r c-  => R.Array r DIM2 c-  -> ((Int, Int) -> (Int, Int))-  -> (((Int, Int) -> c) -> (Int, Int) -> b)-  -> R.Array R.D DIM2 b-traverseR arr getNewDims getNewPx =-  R.traverse arr (dims2sh . checkDims "traverseR" . getNewDims . sh2dims) getNewE-  where-    getNewE getPx = getNewPx (getPx . dims2sh) . sh2dims-    {-# INLINE getNewE #-}-{-# INLINE traverseR #-}--traverse2R-  :: (R.Source r2 c1, R.Source r1 c)-  => R.Array r1 DIM2 c-  -> R.Array r2 DIM2 c1-  -> ((Int, Int) -> (Int, Int) -> (Int, Int))-  -> (((Int, Int) -> c) -> ((Int, Int) -> c1) -> (Int, Int) -> c2)-  -> R.Array R.D DIM2 c2-traverse2R arr1 arr2 getNewDims getNewPx =-  R.traverse2 arr1 arr2 getNewSh getNewE-  where getNewE getPx1 getPx2 = getNewPx (getPx1 . dims2sh) (getPx2 . dims2sh) . sh2dims-        {-# INLINE getNewE #-}-        getNewSh !sh1 !sh2 =-          dims2sh . checkDims "traverse2R" $ getNewDims (sh2dims sh1) (sh2dims sh2)-        {-# INLINE getNewSh #-}-{-# INLINE traverse2R #-}--backpermuteR-  :: R.Source r e-  => R.Array r DIM2 e-  -> (Int, Int)-  -> ((Int, Int) -> (Int, Int))-  -> R.Array R.D DIM2 e-backpermuteR arr newDims g =-  R.backpermute-    (dims2sh (checkDims "backpermuteR" newDims))-    (dims2sh . g . sh2dims)-    arr-{-# INLINE backpermuteR #-}---fromListsR :: Unbox a => [[a]] -> R.Array R.U DIM2 a-fromListsR ls =-  if all (== n) (P.map length ls)-    then R.fromListUnboxed (Z :. m :. n) . concat $ ls-    else error "fromListsR: Inner lists do not all have an equal length."-  where-    !(m, n) = checkDims "fromListsR" (length ls, length $ head ls)-{-# INLINE fromListsR #-}----multR-  :: (Num a, Unbox a, R.Elt a)-  => R.Array R.U DIM2 a -> R.Array R.U DIM2 a -> R.Array R.D DIM2 a-multR arr1 arr2 =-  if n1 /= m2-    then error $-         "Inner dimensions of multiplied images must be the same, but received: " ++ ""-         --show img1 ++ " X " ++ show img2-    else R.fromFunction (Z :. m1 :. n2) $ getPx-  where-    (Z :. m1 :. n1) = R.extent arr1-    (Z :. m2 :. n2) = R.extent arr2-    getPx (Z :. i :. j) =-      R.sumAllS-        (R.slice arr1 (R.Any :. (i :: Int) :. R.All) R.*^-         R.slice arr2 (R.Any :. (j :: Int)))-    {-# INLINE getPx #-}-{-# INLINE multR #-}---singletonR :: Unbox e => e -> R.Array R.U DIM2 e-singletonR px = R.fromUnboxed (Z :. 1 :. 1) $ V.singleton px---getDelayedS :: Array RS cs e => Image RS cs e -> R.Array R.D DIM2 (Pixel cs e)-getDelayedS (SUImage arr) = R.delay arr-getDelayedS (SDImage arr) = arr-getDelayedS (SScalar px)  = R.fromFunction (Z :. 1 :. 1) (const px)-{-# INLINE getDelayedS #-}--getDelayedP :: Array RP cs e => Image RP cs e -> R.Array R.D DIM2 (Pixel cs e)-getDelayedP (PUImage arr) = R.delay arr-getDelayedP (PDImage arr) = arr-getDelayedP (PScalar px)  = R.fromFunction (Z :. 1 :. 1) (const px)-{-# INLINE getDelayedP #-}----- | Changes computation strategy. Will casue all fused operations to be computed.-instance Exchangable RP RS where-  -  exchange _ (PScalar px)   = SScalar px-  exchange _ (PUImage arr)  = SUImage arr-  exchange r img@(PDImage _) = exchange r (compute img)-  {-# INLINE exchange #-}----- | Changes computation strategy. Will casue all fused operations to be computed.-instance Exchangable RS RP where-  -  exchange _ (SScalar px)   = PScalar px-  exchange _ (SUImage arr)  = PUImage arr-  exchange r img@(SDImage _) = exchange r (compute img)-  {-# INLINE exchange #-}----- | O(1) - Changes to Repa representation.-instance Exchangable VU RS where-  exchange _ img@(dims -> (1, 1)) = singleton (img `index` (0, 0))-  exchange _ img = SUImage . R.fromUnboxed (dims2sh $ dims img) . toUnboxedVector $ img-  {-# INLINE exchange #-}----- | O(1) - Changes to Repa representation.-instance Exchangable VU RP where-  exchange _ img@(dims -> (1, 1)) = singleton (img `index` (0, 0))-  exchange _ img = PUImage . R.fromUnboxed (dims2sh $ dims img) . toUnboxedVector $ img-  {-# INLINE exchange #-}----- | O(1) - Changes to Vector representation.-instance Exchangable RS VU where-  exchange _ = toManifest-  {-# INLINE exchange #-}----- | O(1) - Changes to Vector representation.-instance Exchangable RP VU where-  exchange _ = toManifest-  {-# INLINE exchange #-}----- | Create a sequential image from a 2D Repa delayed array.-fromRepaArrayS :: R.Array R.D DIM2 (Pixel cs e) -> Image RS cs e-fromRepaArrayS = SDImage----- | Create a parallel image from a 2D Repa delayed array.-fromRepaArrayP :: R.Array R.D DIM2 (Pixel cs e) -> Image RP cs e-fromRepaArrayP = PDImage----- | Retrieve an underlying Repa array from an image.-toRepaArray-  :: (Array arr cs e, Array RS cs e, Exchangable arr RS)-  => Image arr cs e -> R.Array R.U DIM2 (Pixel cs e)-toRepaArray img =-  case compute (exchange RS img) of-    SUImage arr -> arr-    SDImage arr -> R.computeS arr -- shouldn't occur, but for completeness-    SScalar px -> R.computeS $ R.fromFunction (Z :. 1 :. 1) $ const px--instance R.Elt Bit where-  touch (Bit w) = R.touch w-  {-# INLINE touch #-}-  -  zero     = 0-  {-# INLINE zero #-}-  -  one      = 1-  {-# INLINE one #-}---instance (ColorSpace cs, R.Elt e, Num e) => R.Elt (Pixel cs e) where-  touch !px = P.mapM_ (R.touch . getPxCh px) (enumFrom (toEnum 0)) -  {-# INLINE touch #-}-  -  zero     = 0-  {-# INLINE zero #-}-  -  one      = 1-  {-# INLINE one #-}--
+ src/Graphics/Image/Interface/Repa/Storable.hs view
@@ -0,0 +1,275 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module      : Graphics.Image.Interface.Repa.Storable+-- Copyright   : (c) Alexey Kuleshevich 2017+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>+-- Stability   : experimental+-- Portability : non-portable+--+module Graphics.Image.Interface.Repa.Storable (+  RSS(..), RPS(..), Image(..)+  ) where++import Prelude as P+import Data.Array.Repa.Index+import qualified Data.Array.Repa as R +import qualified Data.Array.Repa.Eval as R+import qualified Data.Array.Repa.Repr.ForeignPtr as R+import qualified Data.Vector.Storable as VS+import Foreign.Storable++import Graphics.Image.Interface as I+import Graphics.Image.Interface.Repa.Generic+import qualified Graphics.Image.Interface.Vector.Storable as IVS+import qualified Graphics.Image.Interface.Vector.Unboxed as IVU++++-- | Repa Array representation backed by Storable Vector, which is computed sequentially. +data RSS = RSS++-- | Repa Array representation backed by Storable Vector, which is computed in parallel.+data RPS = RPS++instance Show RSS where+  show RSS = "RepaSequentialStorable"++instance Show RPS where+  show RPS = "RepaParallelStorable"+  ++type instance Repr (RS IVS.S) = R.F++type instance Repr (RP IVS.S) = R.F+++instance SuperClass RSS cs e => BaseArray RSS cs e where+  type SuperClass RSS cs e =+    (ColorSpace cs e, Num (Pixel cs e),+     Storable e, Storable (Pixel cs e),+     IVU.Unbox e, IVU.Unbox (Components cs e), +     R.Elt e, R.Elt (Pixel cs e))+  +  data Image RSS cs e = SSImage !(Image (RS IVS.S) cs e)+                       +  dims (SSImage img) = dims img+  {-# INLINE dims #-}+++instance (BaseArray RSS cs e) => Array RSS cs e where++  type Manifest RSS = IVS.VS+  +  makeImage !sz f = SSImage (makeImage sz f)+  {-# INLINE makeImage #-}+ +  makeImageWindowed !sz !w f = SSImage . makeImageWindowed sz w f+  {-# INLINE makeImageWindowed #-}+ +  singleton = SSImage . I.singleton+  {-# INLINE singleton #-}++  index00 (SSImage img) = index00 img+  {-# INLINE index00 #-}++  map f (SSImage img) = SSImage (I.map f img)+  {-# INLINE map #-}++  imap f (SSImage img) = SSImage (I.imap f img)+  {-# INLINE imap #-}++  zipWith f (SSImage img1) (SSImage img2) = SSImage (I.zipWith f img1 img2)+  {-# INLINE zipWith #-}++  izipWith f (SSImage img1) (SSImage img2) = SSImage (I.izipWith f img1 img2)+  {-# INLINE izipWith #-}++  traverse (SSImage img) f g = SSImage (I.traverse img f g)+  {-# INLINE traverse #-}++  traverse2 (SSImage img1) (SSImage img2) f g = SSImage (I.traverse2 img1 img2 f g)+  {-# INLINE traverse2 #-}++  transpose (SSImage img) = SSImage (I.transpose img)+  {-# INLINE transpose #-}++  backpermute !sz g (SSImage img) = SSImage (I.backpermute sz g img)+  {-# INLINE backpermute #-}++  fromLists = SSImage . fromLists+  {-# INLINE fromLists #-}++  fold f !px0 (SSImage img) = fold f px0 img+  {-# INLINE fold #-}++  foldIx f !px0 (SSImage img) = foldIx f px0 img+  {-# INLINE foldIx #-}++  eq (SSImage img1) (SSImage img2) = img1 == img2+  {-# INLINE eq #-}++  compute (SSImage img) = SSImage (compute img)+  {-# INLINE compute #-}++  (|*|) (SSImage img1) (SSImage img2) = SSImage (img1 |*| img2)+  {-# INLINE (|*|) #-}++  toManifest (SSImage (SScalar px)) = I.singleton px+  toManifest (SSImage (STImage arr)) = fromRepaArrayStorable arr+  toManifest !img = toManifest (compute img)+  {-# INLINE toManifest #-}++++instance SuperClass RPS cs e => BaseArray RPS cs e where+  type SuperClass RPS cs e =+    (ColorSpace cs e, Num (Pixel cs e),+     Storable e, Storable (Pixel cs e),+     IVU.Unbox e, IVU.Unbox (Components cs e),+     R.Elt e, R.Elt (Pixel cs e))+  +  data Image RPS cs e = PSImage !(Image (RP IVS.S) cs e)+                       +  dims (PSImage img) = dims img+  {-# INLINE dims #-}+++instance (BaseArray RPS cs e) => Array RPS cs e where++  type Manifest RPS = IVS.VS+  +  makeImage !sz f = PSImage (makeImage sz f)+  {-# INLINE makeImage #-}+ +  makeImageWindowed !sz !w f = PSImage . makeImageWindowed sz w f+  {-# INLINE makeImageWindowed #-}+ +  singleton = PSImage . singleton+  {-# INLINE singleton #-}++  index00 (PSImage img) = index00 img+  {-# INLINE index00 #-}++  map f (PSImage img) = PSImage (I.map f img)+  {-# INLINE map #-}++  imap f (PSImage img) = PSImage (I.imap f img)+  {-# INLINE imap #-}++  zipWith f (PSImage img1) (PSImage img2) = PSImage (I.zipWith f img1 img2)+  {-# INLINE zipWith #-}++  izipWith f (PSImage img1) (PSImage img2) = PSImage (I.izipWith f img1 img2)+  {-# INLINE izipWith #-}++  traverse (PSImage img) f g = PSImage (I.traverse img f g)+  {-# INLINE traverse #-}++  traverse2 (PSImage img1) (PSImage img2) f g = PSImage (I.traverse2 img1 img2 f g)+  {-# INLINE traverse2 #-}++  transpose (PSImage img) = PSImage (I.transpose img)+  {-# INLINE transpose #-}++  backpermute !sz g (PSImage img) = PSImage (backpermute sz g img)+  {-# INLINE backpermute #-}++  fromLists = PSImage . fromLists+  {-# INLINE fromLists #-}++  fold f !px0 (PSImage img) = I.fold f px0 img+  {-# INLINE fold #-}++  foldIx f !px0 (PSImage img) = I.foldIx f px0 img+  {-# INLINE foldIx #-}++  eq (PSImage img1) (PSImage img2) = img1 == img2+  {-# INLINE eq #-}++  compute (PSImage img) = PSImage (compute img)+  {-# INLINE compute #-}++  (|*|) (PSImage img1) (PSImage img2) = PSImage (img1 |*| img2)+  {-# INLINE (|*|) #-}++  toManifest (PSImage (PScalar px)) = singleton px+  toManifest (PSImage (PTImage arr)) = fromRepaArrayStorable arr+  toManifest !img = toManifest (compute img)+  {-# INLINE toManifest #-}+++-- | Changes computation strategy. Will casue all fused operations to be computed.+instance Exchangable RPS RSS where+  +  exchange _ (PSImage img) = SSImage (toRS img)+  {-# INLINE exchange #-}+++-- | Changes computation strategy. Will casue all fused operations to be computed.+instance Exchangable RSS RPS where+  +  exchange _ (SSImage img) = PSImage (toRP img)+  {-# INLINE exchange #-}+++-- | O(1) - Changes to Repa representation.+instance Exchangable IVS.VS RSS where+  exchange _ !img@(dims -> (1, 1)) = singleton (index00 img)+  exchange _ !img =+    SSImage . STImage . toRepaArrayStorable $ img+  {-# INLINE exchange #-}+++-- | O(1) - Changes to Repa representation.+instance Exchangable IVS.VS RPS where+  exchange _ !img@(dims -> (1, 1)) = singleton (index00 img)+  exchange _ !img =+    PSImage . PTImage . toRepaArrayStorable $ img+  {-# INLINE exchange #-}+++-- | Changes to Vector representation.+instance Exchangable RSS IVS.VS where+  exchange _ = toManifest+  {-# INLINE exchange #-}+++-- | Changes to Vector representation.+instance Exchangable RPS IVS.VS where+  exchange _ = toManifest+  {-# INLINE exchange #-}+++fromRepaArrayStorable+  :: forall cs e.+     Array IVS.VS cs e+  => R.Array R.F DIM2 (Pixel cs e) -> Image IVS.VS cs e+fromRepaArrayStorable !arr =+  IVS.fromStorableVector (sh2ix (R.extent arr)) $+  VS.unsafeFromForeignPtr0 (R.toForeignPtr arr) sz+  where+    !sz = sizeOf (undefined :: Pixel cs e) * m * n+    (Z :. m :. n) = R.extent arr+++toRepaArrayStorable+  :: forall cs e.+     Array IVS.VS cs e+  => Image IVS.VS cs e -> R.Array R.F DIM2 (Pixel cs e)+toRepaArrayStorable !img+  | sz == sz' = R.fromForeignPtr (ix2sh (dims img)) fp+  | otherwise = error $ "toRepaArrayStorable: (impossible) Vector size mismatch: " +++                show sz ++ " vs " ++ show sz'+  where+    !(fp, sz) = VS.unsafeToForeignPtr0 $ IVS.toStorableVector img+    !sz' = sizeOf (undefined :: Pixel cs e) * m * n+    !(m, n) = dims img
+ src/Graphics/Image/Interface/Repa/Unboxed.hs view
@@ -0,0 +1,243 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module      : Graphics.Image.Interface.Repa.Unboxed+-- Copyright   : (c) Alexey Kuleshevich 2017+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>+-- Stability   : experimental+-- Portability : non-portable+--+module Graphics.Image.Interface.Repa.Unboxed (+  RSU(..), RPU(..), Image(..)+  ) where++import Prelude as P+import qualified Data.Array.Repa as R +import qualified Data.Array.Repa.Eval as R++import Graphics.Image.Interface as I+import Graphics.Image.Interface.Repa.Generic+import qualified Graphics.Image.Interface.Vector.Unboxed as IVU+++-- | Repa Array representation backed by Unboxed Vector, which is computed sequentially. +data RSU = RSU++-- | Repa Array representation backed by Unboxed Vector, which is computed in parallel.+data RPU = RPU++instance Show RSU where+  show RSU = "RepaSequentialUnboxed"++instance Show RPU where+  show RPU = "RepaParallelUnboxed"+  ++type instance Repr (RS IVU.U) = R.U++type instance Repr (RP IVU.U) = R.U+++instance SuperClass RSU cs e => BaseArray RSU cs e where+  type SuperClass RSU cs e =+    (ColorSpace cs e, Num (Pixel cs e),+     IVU.Unbox e, IVU.Unbox (Components cs e),+     R.Elt e, R.Elt (Pixel cs e))+  +  data Image RSU cs e = SUImage !(Image (RS IVU.U) cs e)+                       +  dims (SUImage img) = dims img+  {-# INLINE dims #-}+++instance (BaseArray RSU cs e) => Array RSU cs e where++  type Manifest RSU = IVU.VU+  +  makeImage !sz f = SUImage (makeImage sz f)+  {-# INLINE makeImage #-}+ +  makeImageWindowed !sz !w f = SUImage . makeImageWindowed sz w f+  {-# INLINE makeImageWindowed #-}+ +  singleton = SUImage . singleton+  {-# INLINE singleton #-}++  index00 (SUImage img) = index00 img+  {-# INLINE index00 #-}++  map f (SUImage img) = SUImage (I.map f img)+  {-# INLINE map #-}++  imap f (SUImage img) = SUImage (I.imap f img)+  {-# INLINE imap #-}++  zipWith f (SUImage img1) (SUImage img2) = SUImage (I.zipWith f img1 img2)+  {-# INLINE zipWith #-}++  izipWith f (SUImage img1) (SUImage img2) = SUImage (I.izipWith f img1 img2)+  {-# INLINE izipWith #-}++  traverse (SUImage img) f g = SUImage (I.traverse img f g)+  {-# INLINE traverse #-}++  traverse2 (SUImage img1) (SUImage img2) f g = SUImage (I.traverse2 img1 img2 f g)+  {-# INLINE traverse2 #-}++  transpose (SUImage img) = SUImage (I.transpose img)+  {-# INLINE transpose #-}++  backpermute !sz g (SUImage img) = SUImage (backpermute sz g img)+  {-# INLINE backpermute #-}++  fromLists = SUImage . fromLists+  {-# INLINE fromLists #-}++  fold f !px0 (SUImage img) = fold f px0 img+  {-# INLINE fold #-}++  foldIx f !px0 (SUImage img) = foldIx f px0 img+  {-# INLINE foldIx #-}++  eq (SUImage img1) (SUImage img2) = img1 == img2+  {-# INLINE eq #-}++  compute (SUImage img) = SUImage (compute img)+  {-# INLINE compute #-}++  (|*|) (SUImage img1) (SUImage img2) = SUImage (img1 |*| img2)+  {-# INLINE (|*|) #-}++  toManifest (SUImage (SScalar px)) = singleton px+  toManifest (SUImage (STImage arr)) =+    IVU.fromUnboxedVector (sh2ix (R.extent arr)) (R.toUnboxed arr)+  toManifest !img = toManifest (compute img)+  {-# INLINE toManifest #-}++++instance SuperClass RPU cs e => BaseArray RPU cs e where+  type SuperClass RPU cs e =+    (ColorSpace cs e, Num (Pixel cs e),+     IVU.Unbox e, IVU.Unbox (Components cs e),+     R.Elt e, R.Elt (Pixel cs e))+  +  data Image RPU cs e = PUImage !(Image (RP IVU.U) cs e)+                       +  dims (PUImage img) = dims img+  {-# INLINE dims #-}+++instance (BaseArray RPU cs e) => Array RPU cs e where++  type Manifest RPU = IVU.VU+  +  makeImage !sz f = PUImage (makeImage sz f)+  {-# INLINE makeImage #-}+ +  makeImageWindowed !sz !w f = PUImage . makeImageWindowed sz w f+  {-# INLINE makeImageWindowed #-}+ +  singleton = PUImage . singleton+  {-# INLINE singleton #-}++  index00 (PUImage img) = index00 img+  {-# INLINE index00 #-}++  map f (PUImage img) = PUImage (I.map f img)+  {-# INLINE map #-}++  imap f (PUImage img) = PUImage (I.imap f img)+  {-# INLINE imap #-}++  zipWith f (PUImage img1) (PUImage img2) = PUImage (I.zipWith f img1 img2)+  {-# INLINE zipWith #-}++  izipWith f (PUImage img1) (PUImage img2) = PUImage (I.izipWith f img1 img2)+  {-# INLINE izipWith #-}++  traverse (PUImage img) f g = PUImage (I.traverse img f g)+  {-# INLINE traverse #-}++  traverse2 (PUImage img1) (PUImage img2) f g = PUImage (I.traverse2 img1 img2 f g)+  {-# INLINE traverse2 #-}++  transpose (PUImage img) = PUImage (I.transpose img)+  {-# INLINE transpose #-}++  backpermute !sz g (PUImage img) = PUImage (backpermute sz g img)+  {-# INLINE backpermute #-}++  fromLists = PUImage . fromLists+  {-# INLINE fromLists #-}++  fold f !px0 (PUImage img) = I.fold f px0 img+  {-# INLINE fold #-}++  foldIx f !px0 (PUImage img) = I.foldIx f px0 img+  {-# INLINE foldIx #-}++  eq (PUImage img1) (PUImage img2) = img1 == img2+  {-# INLINE eq #-}++  compute (PUImage img) = PUImage (compute img)+  {-# INLINE compute #-}++  (|*|) (PUImage img1) (PUImage img2) = PUImage (img1 |*| img2)+  {-# INLINE (|*|) #-}++  toManifest (PUImage (PScalar px)) = singleton px+  toManifest (PUImage (PTImage arr)) =+    IVU.fromUnboxedVector (sh2ix (R.extent arr)) (R.toUnboxed arr)+  toManifest !img = toManifest (compute img)+  {-# INLINE toManifest #-}+++-- | Changes computation strategy. Will casue all fused operations to be computed.+instance Exchangable RPU RSU where+  +  exchange _ (PUImage img)  = SUImage (toRS img)+  {-# INLINE exchange #-}+++-- | Changes computation strategy. Will casue all fused operations to be computed.+instance Exchangable RSU RPU where+  +  exchange _ (SUImage img)  = PUImage (toRP img)+  {-# INLINE exchange #-}+++-- | O(1) - Changes to Repa representation.+instance Exchangable IVU.VU RSU where+  exchange _ img@(dims -> (1, 1)) = singleton (index00 img)+  exchange _ img =+    SUImage . STImage . R.fromUnboxed (ix2sh $ dims img) . IVU.toUnboxedVector $ img+  {-# INLINE exchange #-}+++-- | O(1) - Changes to Repa representation.+instance Exchangable IVU.VU RPU where+  exchange _ img@(dims -> (1, 1)) = singleton (index00 img)+  exchange _ img =+    PUImage . PTImage . R.fromUnboxed (ix2sh $ dims img) . IVU.toUnboxedVector $ img+  {-# INLINE exchange #-}+++-- | Changes to Vector representation.+instance Exchangable RSU IVU.VU where+  exchange _ = toManifest+  {-# INLINE exchange #-}+++-- | Changes to Vector representation.+instance Exchangable RPU IVU.VU where+  exchange _ = toManifest+  {-# INLINE exchange #-}
src/Graphics/Image/Interface/Vector.hs view
@@ -1,66 +1,35 @@-{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE MultiParamTypeClasses #-} -- | -- Module      : Graphics.Image.Interface.Vector--- Copyright   : (c) Alexey Kuleshevich 2016+-- Copyright   : (c) Alexey Kuleshevich 2017 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental -- Portability : non-portable -- module Graphics.Image.Interface.Vector (-  -- * Construction-  makeImage, fromLists, fromUnboxedVector, toUnboxedVector,   -- * Representation-  VU(..),+  VU(..), VS(..),+  -- * Conversion+  fromUnboxedVector, toUnboxedVector,+  fromStorableVector, toStorableVector,   -- * Linear index conversion   toIx, fromIx   ) where -import Graphics.Image.Interface hiding (makeImage, fromLists)-import qualified Graphics.Image.Interface as I (makeImage, fromLists)+import Data.Vector as V (convert)+import Graphics.Image.Interface+import Graphics.Image.Interface.Vector.Generic import Graphics.Image.Interface.Vector.Unboxed+import Graphics.Image.Interface.Vector.Storable  --- | Create an image with 'VU' (Vector Unboxed) representation and pixels of 'Double'--- precision. Note, that it is essential for 'Double' precision pixels to keep values--- normalized in the @[0, 1]@ range in order for an image to be written to file--- properly.------ >>> let grad_gray = makeImage (200, 200) (\(i, j) -> PixelY (fromIntegral i)/200 * (fromIntegral j)/200)------ Because all 'Pixel's and 'Image's are installed into 'Num', above is equivalent to:------ >>> let grad_gray = makeImage (200, 200) (\(i, j) -> PixelY $ fromIntegral (i*j)) / (200*200)--- >>> writeImage "images/grad_gray.png" grad_gray------ Creating color images is just as easy.------ >>> let grad_color = makeImage (200, 200) (\(i, j) -> PixelRGB (fromIntegral i) (fromIntegral j) (fromIntegral (i + j))) / 400--- >>> writeImage "images/grad_color.png" grad_color------ <<images/grad_gray.png>> <<images/grad_color.png>>----makeImage :: Array VU cs Double =>-             (Int, Int) -- ^ (@m@ rows, @n@ columns) - dimensions of a new image.-          -> ((Int, Int) -> Pixel cs Double)-             -- ^ A function that takes (@i@-th row, and @j@-th column) as an argument-             -- and returns a pixel for that location.-          -> Image VU cs Double-makeImage = I.makeImage-{-# INLINE makeImage #-}+instance Exchangable VU VS where+  exchange _ (VUImage (VScalar px))   = VSImage (VScalar px)+  exchange _ (VUImage (VImage m n v)) = VSImage (VImage m n (V.convert v))  --- | Construct an image from a nested rectangular shaped list of pixels.--- Length of an outer list will constitute @m@ rows, while the length of inner lists ---- @n@ columns. All of the inner lists must be the same length and greater than @0@.------ >>> fromLists [[PixelY (fromIntegral (i*j) / 60000) | j <- [1..300]] | i <- [1..200]]--- <Image VectorUnboxed Y (Double): 200x300>------ <<images/grad_fromLists.png>>----fromLists :: Array VU cs e =>-             [[Pixel cs e]]-          -> Image VU cs e-fromLists = I.fromLists-{-# INLINE fromLists #-}+instance Exchangable VS VU where+  exchange _ (VSImage (VScalar px))   = VUImage (VScalar px)+  exchange _ (VSImage (VImage m n v)) = VUImage (VImage m n (V.convert v))
+ src/Graphics/Image/Interface/Vector/Generic.hs view
@@ -0,0 +1,292 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module      : Graphics.Image.Interface.Vector.Generic+-- Copyright   : (c) Alexey Kuleshevich 2017+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>+-- Stability   : experimental+-- Portability : non-portable+--+module Graphics.Image.Interface.Vector.Generic (+  V(..), Repr, Image(..), fromVector, toVector+  ) where++import Prelude hiding (map, zipWith)+import qualified Prelude as P (map)+import Control.DeepSeq (NFData, deepseq)+import Control.Monad+import Control.Monad.ST+#if !MIN_VERSION_base(4,8,0)+import Data.Functor+#endif+import Data.Primitive.MutVar+import qualified Data.Vector.Unboxed as VU+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Generic.Mutable as MVG+import Graphics.Image.Interface as I++-- | Generic 'Vector' representation.+data V r = V r++type family Repr arr :: * -> *++instance Show r => Show (V r) where+  show r = "Vector " ++ show r++instance SuperClass (V r) cs e => BaseArray (V r) cs e where+  type SuperClass (V r) cs e = (Show r, ColorSpace cs e, Num (Pixel cs e),+                                VG.Vector (Repr (V r)) (Pixel cs e), VG.Vector (Repr (V r)) Int,+                                VG.Vector (Repr (V r)) Bool, NFData ((Repr (V r)) (Pixel cs e)))++  data Image (V r) cs e = VScalar !(Pixel cs e)+                        | VImage {-# UNPACK #-} !Int+                                 {-# UNPACK #-} !Int+                                 !((Repr (V r)) (Pixel cs e))++  dims (VImage m n _) = (m, n)+  dims (VScalar _)    = (1, 1)+  {-# INLINE dims #-}+++instance (MArray (V r) cs e, BaseArray (V r) cs e) => Array (V r) cs e where++  type Manifest (V r) = V r++  makeImage !(checkDims "(V r).makeImage" -> (m, n)) f =+    VImage m n $ VG.generate (m * n) (f . toIx n)+  {-# INLINE makeImage #-}++  makeImageWindowed sz !((it, jt), (ib, jb)) getWindowPx getBorderPx =+    VImage m n $ VG.create generate where+      !(m, n) = checkDims "(V r).makeImageWindowed" sz+      nestedLoop :: (VG.Mutable (Repr (V r))) s (Pixel cs e)+                 -> ((Int, Int) -> Pixel cs e)+                 -> Int -> Int -> Int -> Int+                 -> ST s ()+      nestedLoop !mv !getPx !fi !fj !ti !tj = do+        VU.forM_ (VU.enumFromN fi (ti-1)) $ \i ->+          VU.forM_ (VU.enumFromN fj (tj-1)) $ \j ->+            MVG.write mv (fromIx n (i,j)) (getPx (i, j))+      {-# INLINE nestedLoop #-}+      generate :: ST s ((VG.Mutable (Repr (V r))) s (Pixel cs e))+      generate = do+        mv <- MVG.unsafeNew (m*n)+        nestedLoop mv getBorderPx 0 0 ib n+        nestedLoop mv getBorderPx it 0 ib jt+        nestedLoop mv getWindowPx it jt ib jb+        nestedLoop mv getBorderPx it jb ib n+        nestedLoop mv getBorderPx ib 0 m n+        return mv+      {-# INLINE generate #-}+  {-# INLINE makeImageWindowed #-}+  +  singleton = VScalar+  {-# INLINE singleton #-}++  index00 (VScalar px) = px+  index00 (VImage _ _ v) = v VG.! 0+  {-# INLINE index00 #-}+  +  map f (VScalar px)   = VScalar (f px)+  map f (VImage m n v) = VImage m n (VG.map f v)+  {-# INLINE map #-}++  imap f (VScalar px)   = VScalar (f (0, 0) px)+  imap f (VImage m n v) = VImage m n (VG.imap (\ !k !px -> f (toIx n k) px) v)+  {-# INLINE imap #-}+  +  zipWith f (VScalar px1) (VScalar px2)    = VScalar (f px1 px2)+  zipWith f (VScalar px1) (VImage m n v2) = VImage m n (VG.map (f px1) v2)+  zipWith f (VImage m n v1) (VScalar px2) = VImage m n (VG.map (`f` px2) v1)+  zipWith f img1@(VImage m1 n1 v1) img2@(VImage m2 n2 v2) =+    if m1 /= m2 || n1 /= n2+    then error ("zipWith: Images must be of the same dimensions, received: "+++                show img1++" and "++show img2++".")+    else VImage m1 n1 (VG.zipWith f v1 v2)+  {-# INLINE zipWith #-}++  izipWith f (VScalar px1) (VScalar px2)    = VScalar (f (0, 0) px1 px2)+  izipWith f (VScalar px1) (VImage m n v2) =+    VImage m n (VG.imap (\ !k !px2 -> f (toIx n k) px1 px2) v2)+  izipWith f (VImage m n v1) (VScalar px2) =+    VImage m n (VG.imap (\ !k !px1 -> f (toIx n k) px1 px2) v1)+  izipWith f img1@(VImage m1 n1 v1) img2@(VImage m2 n2 v2) =+    if m1 /= m2 || n1 /= n2+    then error ("izipWith: Images must be of the same dimensions, received: "+++                show img1++" and "++show img2++".")+    else VImage m1 n1 (VG.izipWith (\ !k !px1 !px2 -> f (toIx n1 k) px1 px2) v1 v2)+  {-# INLINE izipWith #-}++  traverse !img getNewDims getNewPx = makeImage (getNewDims (dims img)) (getNewPx (index img))+  {-# INLINE traverse #-}++  traverse2 !img1 !img2 getNewDims getNewPx =+    makeImage (getNewDims (dims img1) (dims img2)) (getNewPx (index img1) (index img2))+  {-# INLINE traverse2 #-}++  -- TODO: switch directly to VG.unsafeBackpermute (no need to check ixs)+  transpose !img = backpermute (n, m) movePx img where+    !(m, n) = dims img+    movePx !(i, j) = (j, i)+    {-# INLINE movePx #-}+  {-# INLINE transpose #-}++  -- TODO: add index verification and switch to VG.unsafeBackpermute+  backpermute !(checkDims "(V r).backpermute" -> (m, n)) !f (VImage _ n' v) =+    VImage m n $ VG.backpermute v $ VG.generate (m*n) (fromIx n' . f . toIx n)+  backpermute !sz _ (VScalar px) = makeImage sz (const px)+  {-# INLINE backpermute #-}+  +  fromLists !ls = if all (== n) (P.map length ls)+                  then VImage m n . VG.fromList . concat $ ls+                  else error "fromLists: Inner lists are of different lengths."+    where+      !(m, n) = checkDims "(V r).fromLists" (length ls, length $ head ls)+  {-# INLINE fromLists #-}++  fold !f !px0 (VImage _ _ v) = VG.foldl' f px0 v+  fold !f !px0 (VScalar px)    = f px0 px+  {-# INLINE fold #-}++  foldIx !f !px0 (VImage _ n v) = VG.ifoldl' f' px0 v where+    f' !acc !k !px = f acc (toIx n k) px+  foldIx !f !px0 (VScalar px)    = f px0 (0,0) px+  {-# INLINE foldIx #-}++  (|*|) img1@(VImage m1 n1 v1) !img2@VImage {} =+    if n1 /= m2 +    then error ("Inner dimensions of multiplying images must be the same, but received: "+++                show img1 ++" X "++ show img2)+    else+      makeImage (m1, n2) getPx where+        VImage n2 m2 v2 = transpose img2+        getPx !(i, j) = VG.sum $ VG.zipWith (*) (VG.slice (i*n1) n1 v1) (VG.slice (j*m2) m2 v2)+        {-# INLINE getPx #-}+  (|*|) (VScalar px1) (VScalar px2) = VScalar (px1 * px2)+  (|*|) _ _ = error "Scalar Images cannot be multiplied."+  {-# INLINE (|*|) #-}++  eq (VImage m1 n1 v1) (VImage m2 n2 v2) =+    m1 == m2 && n1 == n2 && VG.all id (VG.zipWith (==) v1 v2)+  eq (VScalar px1)           (VScalar px2) = px1 == px2+  eq (VImage 1 1 v1) (VScalar px2) = v1 VG.! 0 == px2+  eq (VScalar px1) (VImage 1 1 v2) = v2 VG.! 0 == px1+  eq _ _ = False+  {-# INLINE eq #-}++  compute (VImage m n v) = m `seq` n `seq` v `deepseq` (VImage m n v)+  compute (VScalar px)    = px `seq` (VScalar px)+  {-# INLINE compute #-}++  toManifest = id+  {-# INLINE toManifest #-}+++instance BaseArray (V r) cs e => MArray (V r) cs e where+  +  data MImage s (V r) cs e = MVImage !Int !Int ((VG.Mutable (Repr (V r))) s (Pixel cs e))+                            | MVScalar (MutVar s (Pixel cs e))+                              ++  unsafeIndex (VImage _ n v) !ix = VG.unsafeIndex v (fromIx n ix)+  unsafeIndex (VScalar px)     _ = px+  {-# INLINE unsafeIndex #-}++  deepSeqImage (VImage m n v) = m `seq` n `seq` deepseq v+  deepSeqImage (VScalar px)   = seq px+  {-# INLINE deepSeqImage #-}++  foldl f !a (VImage _ _ v) = VG.foldl' f a v+  foldl f !a (VScalar px)   = f a px++  foldr f !a (VImage _ _ v) = VG.foldr' f a v+  foldr f !a (VScalar px)   = f px a+  {-# INLINE foldr #-}++  makeImageM !(checkDims "(V r).makeImageM" -> (m, n)) !f =+    VImage m n <$> VG.generateM (m * n) (f . toIx n)+  {-# INLINE makeImageM #-}++  mapM f (VImage m n v) = VImage m n <$> VG.mapM f v+  mapM f (VScalar px)   = VScalar <$> f px+  {-# INLINE mapM #-}++  mapM_ f (VImage _ _ v) = VG.mapM_ f v+  mapM_ f (VScalar px)    = void $ f px+  {-# INLINE mapM_ #-}++  foldM f !a (VImage _ _ v) = VG.foldM' f a v+  foldM f !a (VScalar px)    = f a px+  {-# INLINE foldM #-}++  foldM_ f !a (VImage _ _ v) = VG.foldM'_ f a v+  foldM_ f !a (VScalar px)    = void $ f a px+  {-# INLINE foldM_ #-}+++  mdims (MVImage m n _) = (m, n)+  mdims (MVScalar _)    = (1, 1)+  {-# INLINE mdims #-}++  thaw (VImage m n v) = MVImage m n <$> VG.thaw v+  thaw (VScalar px)   = MVScalar <$> newMutVar px+  {-# INLINE thaw #-}++  freeze (MVImage m n mv) = VImage m n <$> VG.freeze mv+  freeze (MVScalar mpx)    = VScalar <$> readMutVar mpx+  {-# INLINE freeze #-}++  new (m, n) = MVImage m n <$> MVG.new (m*n)+  {-# INLINE new #-}++  read (MVImage _ n mv) !ix = MVG.read mv (fromIx n ix)+  read (MVScalar mpx)   !ix = do+    unless ((0, 0) == ix) $ error $ "Index out of bounds: " ++ show ix+    readMutVar mpx+  {-# INLINE read #-}++  write (MVImage _ n mv) !ix !px = MVG.write mv (fromIx n ix) px+  write (MVScalar mv)    !ix !px = do+    unless ((0, 0) == ix) $ error $ "Index out of bounds: " ++ show ix+    writeMutVar mv px+  {-# INLINE write #-}++  swap (MVImage _ n mv) !ix1 !ix2 = MVG.swap mv (fromIx n ix1) (fromIx n ix2)+  swap _                _    _    = return ()+  {-# INLINE swap #-}+++-- | Convert an image to a flattened  'Vector'. It is a __O(1)__ opeartion.+--+-- >>> toVector $ makeImage (3, 2) (\(i, j) -> PixelY $ fromIntegral (i+j))+-- fromList [<Luma:(0.0)>,<Luma:(1.0)>,<Luma:(1.0)>,<Luma:(2.0)>,<Luma:(2.0)>,<Luma:(3.0)>]+--+toVector :: VG.Vector (Repr (V r)) (Pixel cs e) => Image (V r) cs e -> (Repr (V r)) (Pixel cs e)+toVector (VImage _ _ v) = v+toVector (VScalar px)   = VG.singleton px+{-# INLINE toVector #-}+++-- | Construct a two dimensional image with @m@ rows and @n@ columns from a flat+--  'Vector' of length @k@. It is a __O(1)__ opeartion. Make sure that @m * n = k@.+--+-- >>> fromVector (200, 300) $ generate 60000 (\i -> PixelY $ fromIntegral i / 60000)+-- <Image Vector Luma: 200x300>+--+-- <<images/grad_fromVector.png>>+-- +fromVector :: (Array (V r) cs e, VG.Vector (Repr (V r)) (Pixel cs e)) => (Int, Int) -> (Repr (V r)) (Pixel cs e) -> Image (V r) cs e+fromVector !(m, n) !v+  | m * n == VG.length v = VImage m n v+  | otherwise = error "fromVector: m * n doesn't equal the length of a Vector."+{-# INLINE fromVector #-}
+ src/Graphics/Image/Interface/Vector/Storable.hs view
@@ -0,0 +1,196 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module      : Graphics.Image.Interface.Vector.Storable+-- Copyright   : (c) Alexey Kuleshevich 2017+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>+-- Stability   : experimental+-- Portability : non-portable+--+module Graphics.Image.Interface.Vector.Storable (+  VS(..), S, Image(..), fromStorableVector, toStorableVector, fromIx, toIx, checkDims+  ) where++import Prelude hiding (map, zipWith)+#if !MIN_VERSION_base(4,8,0)+import Data.Functor+#endif+import qualified Data.Vector.Storable as VS+import Graphics.Image.Interface as I+import Graphics.Image.Interface.Vector.Generic++++-- | Storable 'Vector' representation.+data VS = VS++data S++type instance Repr (V S) = VS.Vector++instance Show S where+  show _ = "Storable"++instance Show VS where+  show _ = "VectorStorable"++instance SuperClass VS cs e => BaseArray VS cs e where+  type SuperClass VS cs e =+    (ColorSpace cs e, Num (Pixel cs e), VS.Storable (Pixel cs e))++  data Image VS cs e = VSImage !(Image (V S) cs e)++  dims (VSImage img) = dims img+  {-# INLINE dims #-}++++instance (MArray VS cs e, BaseArray VS cs e) => Array VS cs e where++  type Manifest VS = VS++  makeImage !sh = VSImage . makeImage sh+  {-# INLINE makeImage #-}++  makeImageWindowed !sh !window f g = VSImage $ makeImageWindowed sh window f g+  {-# INLINE makeImageWindowed #-}+  +  singleton = VSImage . singleton+  {-# INLINE singleton #-}++  index00 (VSImage img) = index00 img+  {-# INLINE index00 #-}+  +  map f (VSImage img) = VSImage $ I.map f img+  {-# INLINE map #-}++  imap f (VSImage img) = VSImage $ I.imap f img+  {-# INLINE imap #-}+  +  zipWith f (VSImage img1) (VSImage img2) = VSImage $ I.zipWith f img1 img2+  {-# INLINE zipWith #-}++  izipWith f (VSImage img1) (VSImage img2) = VSImage $ I.izipWith f img1 img2+  {-# INLINE izipWith #-}++  traverse (VSImage img) f g = VSImage $ I.traverse img f g+  {-# INLINE traverse #-}++  traverse2 (VSImage img1) (VSImage img2) f g = VSImage $ I.traverse2 img1 img2 f g+  {-# INLINE traverse2 #-}++  transpose (VSImage img) = VSImage $ I.transpose img+  {-# INLINE transpose #-}++  backpermute !sz f (VSImage img) = VSImage $ I.backpermute sz f img+  {-# INLINE backpermute #-}+  +  fromLists = VSImage . I.fromLists+  {-# INLINE fromLists #-}++  fold f !px0 (VSImage img) = fold f px0 img+  {-# INLINE fold #-}++  foldIx f !px0 (VSImage img) = foldIx f px0 img+  {-# INLINE foldIx #-}++  (|*|) (VSImage img1) (VSImage img2) = VSImage (img1 |*| img2)+  {-# INLINE (|*|) #-}++  eq (VSImage img1) (VSImage img2) = img1 == img2+  {-# INLINE eq #-}++  compute (VSImage img) = VSImage $! compute img+  {-# INLINE compute #-}++  toManifest = id+  {-# INLINE toManifest #-}++++instance BaseArray VS cs e => MArray VS cs e where+  +  data MImage s VS cs e = MVSImage (MImage s (V S) cs e)+                              ++  unsafeIndex (VSImage img) = unsafeIndex img+  {-# INLINE unsafeIndex #-}++  deepSeqImage (VSImage img) = deepSeqImage img+  {-# INLINE deepSeqImage #-}++  foldl f !px0 (VSImage img) = I.foldl f px0 img+  {-# INLINE foldl #-}++  foldr f !px0 (VSImage img) = I.foldr f px0 img+  {-# INLINE foldr #-}++  makeImageM !sh f = VSImage <$> makeImageM sh f+  {-# INLINE makeImageM #-}++  mapM f (VSImage img) = VSImage <$> I.mapM f img+  {-# INLINE mapM #-}++  mapM_ f (VSImage img) = I.mapM_ f img+  {-# INLINE mapM_ #-}++  foldM f !px0 (VSImage img) = I.foldM f px0 img+  {-# INLINE foldM #-}++  foldM_ f !px0 (VSImage img) = I.foldM_ f px0 img+  {-# INLINE foldM_ #-}++  mdims (MVSImage mimg) = mdims mimg+  {-# INLINE mdims #-}++  thaw (VSImage img) = MVSImage <$> I.thaw img+  {-# INLINE thaw #-}++  freeze (MVSImage img) = VSImage <$> I.freeze img+  {-# INLINE freeze #-}++  new !ix = MVSImage <$> I.new ix+  {-# INLINE new #-}++  read (MVSImage img) = I.read img+  {-# INLINE read #-}++  write (MVSImage img) = I.write img+  {-# INLINE write #-}++  swap (MVSImage img) = I.swap img+  {-# INLINE swap #-}++++-- | Convert an image to a flattened Storable 'VS.Vector'. It is a __O(1)__ opeartion.+--+-- >>> toStorableVector $ makeImage (3, 2) (\(i, j) -> PixelY $ fromIntegral (i+j))+-- fromList [<Luma:(0.0)>,<Luma:(1.0)>,<Luma:(1.0)>,<Luma:(2.0)>,<Luma:(2.0)>,<Luma:(3.0)>]+--+toStorableVector :: Array VS cs e => Image VS cs e -> VS.Vector (Pixel cs e)+toStorableVector (VSImage img) = toVector img+{-# INLINE toStorableVector #-}+++-- | Construct a two dimensional image with @m@ rows and @n@ columns from a flat+-- Storable 'VS.Vector' of length @k@. It is a __O(1)__ opeartion. Make sure that @m * n = k@.+--+-- >>> fromStorableVector (200, 300) $ generate 60000 (\i -> PixelY $ fromIntegral i / 60000)+-- <Image VectorStorable Luma: 200x300>+--+-- <<images/grad_fromVector.png>>+-- +fromStorableVector :: Array VS cs e => (Int, Int) -> VS.Vector (Pixel cs e) -> Image VS cs e+fromStorableVector !sz !v = VSImage $ fromVector sz v+{-# INLINE fromStorableVector #-}
src/Graphics/Image/Interface/Vector/Unboxed.hs view
@@ -5,278 +5,192 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Image.Interface.Vector.Unboxed--- Copyright   : (c) Alexey Kuleshevich 2016+-- Copyright   : (c) Alexey Kuleshevich 2017 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental -- Portability : non-portable -- module Graphics.Image.Interface.Vector.Unboxed (-  VU(..), Image(..), fromUnboxedVector, toUnboxedVector, fromIx, toIx, checkDims+  U, VU(..), VU.Unbox, Image(..), fromUnboxedVector, toUnboxedVector, fromIx, toIx, checkDims   ) where  import Prelude hiding (map, zipWith)-import qualified Prelude as P (map)-import Control.DeepSeq (deepseq)-import Control.Monad (void) #if !MIN_VERSION_base(4,8,0) import Data.Functor #endif-import Data.Typeable (Typeable)-import Data.Vector.Unboxed (Vector, Unbox)-import qualified Data.Vector.Unboxed as V-import qualified Data.Vector.Unboxed.Mutable as MV-import Graphics.Image.Interface+import qualified Data.Vector.Unboxed as VU+import Graphics.Image.Interface as I+import Graphics.Image.Interface.Vector.Generic import Graphics.Image.Interface.Vector.Unboxing()  + -- | Unboxed 'Vector' representation. data VU = VU +data U +type instance Repr (V U) = VU.Vector++instance Show U where+  show _ = "Unboxed"+ instance Show VU where   show _ = "VectorUnboxed" --instance Elt VU cs e => BaseArray VU cs e where-  type Elt VU cs e = (ColorSpace cs, Num e, Unbox e, Typeable e, -                      Unbox (PixelElt cs e), Unbox (Pixel cs e))+instance SuperClass VU cs e => BaseArray VU cs e where+  type SuperClass VU cs e =+    (ColorSpace cs e, Num (Pixel cs e), VU.Unbox (Components cs e)) -  data Image VU cs e = VScalar !(Pixel cs e)-                     | VUImage !Int !Int !(Vector (Pixel cs e))+  data Image VU cs e = VUImage !(Image (V U) cs e) -  dims (VUImage m n _) = (m, n)-  dims (VScalar _)     = (1, 1)+  dims (VUImage img) = dims img   {-# INLINE dims #-}  -instance BaseArray VU cs e => Array VU cs e where +instance (MArray VU cs e, BaseArray VU cs e) => Array VU cs e where+   type Manifest VU = VU -  makeImage !(checkDims "VU.makeImage" -> (m, n)) !f =-    VUImage m n $ V.generate (m * n) (f . toIx n)+  makeImage !sh = VUImage . makeImage sh   {-# INLINE makeImage #-} -  singleton = VScalar+  makeImageWindowed !sh !window f g = VUImage $ makeImageWindowed sh window f g+  {-# INLINE makeImageWindowed #-}+  +  singleton = VUImage . singleton   {-# INLINE singleton #-} -  index00 (VScalar px) = px-  index00 (VUImage _ _ v) = v V.! 0+  index00 (VUImage img) = index00 img   {-# INLINE index00 #-}   -  map !f (VScalar px)    = VScalar (f px)-  map !f (VUImage m n v) = VUImage m n (V.map f v)+  map f (VUImage img) = VUImage $ I.map f img   {-# INLINE map #-} -  imap !f (VScalar px)    = VScalar (f (0, 0) px)-  imap !f (VUImage m n v) = VUImage m n (V.imap (\ !k !px -> f (toIx n k) px) v)+  imap f (VUImage img) = VUImage $ I.imap f img   {-# INLINE imap #-}   -  zipWith !f (VScalar px1) (VScalar px2)    = VScalar (f px1 px2)-  zipWith !f (VScalar px1) (VUImage m n v2) = VUImage m n (V.map (f px1) v2)-  zipWith !f (VUImage m n v1) (VScalar px2) = VUImage m n (V.map (`f` px2) v1)-  zipWith !f img1@(VUImage m1 n1 v1) img2@(VUImage m2 n2 v2) =-    if m1 /= m2 || n1 /= n2-    then error ("zipWith: Images must be of the same dimensions, received: "++-                show img1++" and "++show img2++".")-    else VUImage m1 n1 (V.zipWith f v1 v2)+  zipWith f (VUImage img1) (VUImage img2) = VUImage $ I.zipWith f img1 img2   {-# INLINE zipWith #-} -  izipWith !f (VScalar px1) (VScalar px2)    = VScalar (f (0, 0) px1 px2)-  izipWith !f (VScalar px1) (VUImage m n v2) =-    VUImage m n (V.imap (\ !k !px2 -> f (toIx n k) px1 px2) v2)-  izipWith !f (VUImage m n v1) (VScalar px2) =-    VUImage m n (V.imap (\ !k !px1 -> f (toIx n k) px1 px2) v1)-  izipWith !f img1@(VUImage m1 n1 v1) img2@(VUImage m2 n2 v2) =-    if m1 /= m2 || n1 /= n2-    then error ("izipWith: Images must be of the same dimensions, received: "++-                show img1++" and "++show img2++".")-    else VUImage m1 n1 (V.izipWith (\ !k !px1 !px2 -> f (toIx n1 k) px1 px2) v1 v2)+  izipWith f (VUImage img1) (VUImage img2) = VUImage $ I.izipWith f img1 img2   {-# INLINE izipWith #-} -  traverse !img !getNewDims !getNewPx = makeImage (getNewDims (dims img)) (getNewPx (index img))+  traverse (VUImage img) f g = VUImage $ I.traverse img f g   {-# INLINE traverse #-} -  traverse2 !img1 !img2 !getNewDims !getNewPx =-    makeImage (getNewDims (dims img1) (dims img2)) (getNewPx (index img1) (index img2))+  traverse2 (VUImage img1) (VUImage img2) f g = VUImage $ I.traverse2 img1 img2 f g   {-# INLINE traverse2 #-} -  transpose !img@(dims -> (m, n)) = makeImage (n, m) getPx where-    getPx !(i, j) = index img (j, i)-    {-# INLINE getPx #-}+  transpose (VUImage img) = VUImage $ I.transpose img   {-# INLINE transpose #-} -  backpermute !(checkDims "VU.backpermute" -> (m, n)) !f (VUImage _ n' v) =-    VUImage m n $ V.backpermute v $ V.generate (m*n) (fromIx n' . f . toIx n)-  backpermute !sz _ (VScalar px) = makeImage sz (const px)+  backpermute !sz f (VUImage img) = VUImage $ I.backpermute sz f img   {-# INLINE backpermute #-}   -  fromLists !ls = if isSquare-                  then VUImage m n . V.fromList . concat $ ls-                  else error "fromLists: Inner lists are of different lengths."-    where-      !(m, n) = (length ls, length $ head ls)-      !isSquare = (n > 0) && all (==n) (P.map length ls)+  fromLists = VUImage . I.fromLists   {-# INLINE fromLists #-} -  fold !f !px0 (VUImage _ _ v) = V.foldl' f px0 v-  fold !f !px0 (VScalar px)    = f px0 px+  fold f !px0 (VUImage img) = fold f px0 img   {-# INLINE fold #-} -  (|*|) img1@(VUImage m1 n1 v1) !img2@VUImage {} =-    if n1 /= m2 -    then error ("Inner dimensions of multiplying images must be the same, but received: "++-                show img1 ++" X "++ show img2)-    else-      makeImage (m1, n2) getPx where-        VUImage n2 m2 v2 = transpose img2-        getPx !(i, j) = V.sum $ V.zipWith (*) (V.slice (i*n1) n1 v1) (V.slice (j*m2) m2 v2)-        {-# INLINE getPx #-}-  (|*|) (VScalar px1) (VScalar px2) = VScalar (px1 * px2)-  (|*|) _ _ = error "Scalar Images cannot be multiplied."+  foldIx f !px0 (VUImage img) = foldIx f px0 img+  {-# INLINE foldIx #-}++  (|*|) (VUImage img1) (VUImage img2) = VUImage (img1 |*| img2)   {-# INLINE (|*|) #-} -  eq (VUImage m1 n1 v1) (VUImage m2 n2 v2) =-    m1 == m2 && n1 == n2 && V.all id (V.zipWith (==) v1 v2)-  eq (VScalar px1)           (VScalar px2) = px1 == px2-  eq (VUImage 1 1 v1) (VScalar px2) = v1 V.! 0 == px2-  eq (VScalar px1) (VUImage 1 1 v2) = v2 V.! 0 == px1-  eq _ _ = False+  eq (VUImage img1) (VUImage img2) = img1 == img2   {-# INLINE eq #-} -  compute (VUImage m n v) = m `seq` n `seq` v `deepseq` (VUImage m n v)-  compute (VScalar px)    = px `seq` (VScalar px)+  compute (VUImage img) = VUImage $! compute img   {-# INLINE compute #-}    toManifest = id   {-# INLINE toManifest #-}  -instance Array VU cs e => MArray VU cs e where+instance BaseArray VU cs e => MArray VU cs e where   -  data MImage st VU cs e = MVImage !Int !Int (MV.MVector st (Pixel cs e))-                         | MVScalar (MV.MVector st (Pixel cs e))-+  data MImage s VU cs e = MVUImage (MImage s (V U) cs e)+                               -  unsafeIndex (VUImage _ n v) !ix = V.unsafeIndex v (fromIx n ix)-  unsafeIndex (VScalar px)      _ = px+  unsafeIndex (VUImage img) = unsafeIndex img   {-# INLINE unsafeIndex #-} -  deepSeqImage (VUImage m n v) = m `seq` n `seq` deepseq v-  deepSeqImage (VScalar px)    = seq px+  deepSeqImage (VUImage img) = deepSeqImage img   {-# INLINE deepSeqImage #-} -  foldl !f !a (VUImage _ _ v) = V.foldl' f a v-  foldl !f !a (VScalar px)    = f a px+  foldl f !px0 (VUImage img) = I.foldl f px0 img   {-# INLINE foldl #-} -  foldr !f !a (VUImage _ _ v) = V.foldr' f a v-  foldr !f !a (VScalar px)    = f px a+  foldr f !px0 (VUImage img) = I.foldr f px0 img   {-# INLINE foldr #-} -  makeImageM !(checkDims "VU.makeImageM" -> (m, n)) !f =-    VUImage m n <$> V.generateM (m * n) (f . toIx n)+  makeImageM !sh f = VUImage <$> makeImageM sh f   {-# INLINE makeImageM #-} -  mapM !f (VUImage m n v) = VUImage m n <$> V.mapM f v-  mapM !f (VScalar px)    = VScalar <$> f px+  mapM f (VUImage img) = VUImage <$> I.mapM f img   {-# INLINE mapM #-} -  mapM_ !f (VUImage _ _ v) = V.mapM_ f v-  mapM_ !f (VScalar px)    = void $ f px+  mapM_ f (VUImage img) = I.mapM_ f img   {-# INLINE mapM_ #-} -  foldM !f !a (VUImage _ _ v) = V.foldM' f a v-  foldM !f !a (VScalar px)    = f a px+  foldM f !px0 (VUImage img) = I.foldM f px0 img   {-# INLINE foldM #-} -  foldM_ !f !a (VUImage _ _ v) = V.foldM'_ f a v-  foldM_ !f !a (VScalar px)    = void $ f a px+  foldM_ f !px0 (VUImage img) = I.foldM_ f px0 img   {-# INLINE foldM_ #-} --  mdims (MVImage m n _) = (m, n)-  mdims (MVScalar _)    = (1, 1)+  mdims (MVUImage mimg) = mdims mimg   {-# INLINE mdims #-} -  thaw (VUImage m n v) = MVImage m n <$> V.thaw v-  thaw (VScalar px)    = MVScalar <$> V.thaw (V.singleton px)+  thaw (VUImage img) = MVUImage <$> I.thaw img   {-# INLINE thaw #-} -  freeze (MVImage m n mv) = VUImage m n <$> V.freeze mv-  freeze (MVScalar mv)    = VScalar . (V.! 0) <$> V.freeze mv+  freeze (MVUImage img) = VUImage <$> I.freeze img   {-# INLINE freeze #-} -  new (m, n) = MVImage m n <$> MV.new (m*n)+  new !ix = MVUImage <$> I.new ix   {-# INLINE new #-} -  read (MVImage _ n mv) ix = MV.read mv (fromIx n ix)-  read (MVScalar mv)    _  = MV.read mv 0+  read (MVUImage img) = I.read img   {-# INLINE read #-} -  write (MVImage _ n mv) ix = MV.write mv (fromIx n ix)-  write (MVScalar mv)    _  = MV.write mv 0+  write (MVUImage img) = I.write img   {-# INLINE write #-} -  swap (MVImage _ n mv) ix1 ix2 = MV.swap mv (fromIx n ix1) (fromIx n ix2)-  swap _                _   _   = return ()+  swap (MVUImage img) = I.swap img   {-# INLINE swap #-}  --- | Convert an image to a flattened Unboxed 'Vector'. It is a __O(1)__ opeartion.++-- | Convert an image to a flattened Unboxed 'VU.Vector'. It is a __O(1)__ opeartion. -- -- >>> toUnboxedVector $ makeImage (3, 2) (\(i, j) -> PixelY $ fromIntegral (i+j)) -- fromList [<Luma:(0.0)>,<Luma:(1.0)>,<Luma:(1.0)>,<Luma:(2.0)>,<Luma:(2.0)>,<Luma:(3.0)>] ---toUnboxedVector :: Array VU cs e => Image VU cs e -> Vector (Pixel cs e)-toUnboxedVector (VUImage _ _ v) = v-toUnboxedVector (VScalar px) = V.singleton px+toUnboxedVector :: Array VU cs e => Image VU cs e -> VU.Vector (Pixel cs e)+toUnboxedVector (VUImage img) = toVector img {-# INLINE toUnboxedVector #-}   -- | Construct a two dimensional image with @m@ rows and @n@ columns from a flat--- Unboxed 'Vector' of length @k@. It is a __O(1)__ opeartion. Make sure that @m * n = k@.+-- Unboxed 'VU.Vector' of length @k@. It is a __O(1)__ opeartion. Make sure that @m * n = k@. -- -- >>> fromUnboxedVector (200, 300) $ generate 60000 (\i -> PixelY $ fromIntegral i / 60000) -- <Image VectorUnboxed Luma: 200x300> -- -- <<images/grad_fromVector.png>> -- -fromUnboxedVector :: Array VU cs e => (Int, Int) -> Vector (Pixel cs e) -> Image VU cs e-fromUnboxedVector !(m, n) !v-  | m * n == V.length v = VUImage m n v-  | otherwise = error "fromUnboxedVector: m * n doesn't equal the length of a Vector."+fromUnboxedVector :: Array VU cs e => (Int, Int) -> VU.Vector (Pixel cs e) -> Image VU cs e+fromUnboxedVector !sz !v = VUImage $ fromVector sz v {-# INLINE fromUnboxedVector #-}----- | 2D to a flat vector index conversion.------ __Note__: There is an implicit assumption that @j < n@-fromIx :: Int -- ^ @n@ columns-       -> (Int, Int) -- ^ @(i, j)@ row, column index-       -> Int -- ^ Flat vector index-fromIx !n !(i, j) = n * i + j-{-# INLINE fromIx #-}----- | Flat vector to 2D index conversion.-toIx :: Int -- ^ @n@ columns-     -> Int -- ^ Flat vector index-     -> (Int, Int) -- ^ @(i, j)@ row, column index-toIx !n !k = divMod k n-{-# INLINE toIx #-}---checkDims :: String -> (Int, Int) -> (Int, Int)-checkDims err !ds@(m, n)-  | m <= 0 || n <= 0 = -    error $-    show err ++ ": Image dimensions are expected to be non-negative: " ++ show ds-  | otherwise = ds-{-# INLINE checkDims #-}
src/Graphics/Image/Interface/Vector/Unboxing.hs view
@@ -79,11 +79,11 @@   -- | Unboxing of a `Pixel`.-instance (ColorSpace cs, U.Unbox (PixelElt cs e)) => U.Unbox (Pixel cs e)+instance (ColorSpace cs e, U.Unbox (Components cs e)) => U.Unbox (Pixel cs e) -newtype instance U.MVector s (Pixel cs e) = MV_Pixel (U.MVector s (PixelElt cs e))+newtype instance U.MVector s (Pixel cs e) = MV_Pixel (U.MVector s (Components cs e)) -instance (ColorSpace cs, U.Unbox (PixelElt cs e)) => M.MVector U.MVector (Pixel cs e) where+instance (ColorSpace cs e, U.Unbox (Components cs e)) => M.MVector U.MVector (Pixel cs e) where   basicLength (MV_Pixel mvec) = M.basicLength mvec   {-# INLINE basicLength #-}   basicUnsafeSlice idx len (MV_Pixel mvec) = MV_Pixel (M.basicUnsafeSlice idx len mvec)@@ -92,15 +92,15 @@   {-# INLINE basicOverlaps #-}   basicUnsafeNew len = MV_Pixel `liftM` M.basicUnsafeNew len   {-# INLINE basicUnsafeNew #-}-  basicUnsafeReplicate len val = MV_Pixel `liftM` M.basicUnsafeReplicate len (toElt val)+  basicUnsafeReplicate len val = MV_Pixel `liftM` M.basicUnsafeReplicate len (toComponents val)   {-# INLINE basicUnsafeReplicate #-}-  basicUnsafeRead (MV_Pixel mvec) idx = fromElt `liftM` M.basicUnsafeRead mvec idx+  basicUnsafeRead (MV_Pixel mvec) idx = fromComponents `liftM` M.basicUnsafeRead mvec idx   {-# INLINE basicUnsafeRead #-}-  basicUnsafeWrite (MV_Pixel mvec) idx val = M.basicUnsafeWrite mvec idx (toElt val)+  basicUnsafeWrite (MV_Pixel mvec) idx val = M.basicUnsafeWrite mvec idx (toComponents val)   {-# INLINE basicUnsafeWrite #-}   basicClear (MV_Pixel mvec) = M.basicClear mvec   {-# INLINE basicClear #-}-  basicSet (MV_Pixel mvec) val = M.basicSet mvec (toElt val)+  basicSet (MV_Pixel mvec) val = M.basicSet mvec (toComponents val)   {-# INLINE basicSet #-}   basicUnsafeCopy (MV_Pixel mvec) (MV_Pixel mvec') = M.basicUnsafeCopy mvec mvec'   {-# INLINE basicUnsafeCopy #-}@@ -114,9 +114,9 @@ #endif  -newtype instance U.Vector (Pixel cs e) = V_Pixel (U.Vector (PixelElt cs e))+newtype instance U.Vector (Pixel cs e) = V_Pixel (U.Vector (Components cs e)) -instance (ColorSpace cs, U.Unbox (PixelElt cs e)) => V.Vector U.Vector (Pixel cs e) where+instance (ColorSpace cs e, U.Unbox (Components cs e)) => V.Vector U.Vector (Pixel cs e) where   basicUnsafeFreeze (MV_Pixel mvec) = V_Pixel `liftM` V.basicUnsafeFreeze mvec   {-# INLINE basicUnsafeFreeze #-}   basicUnsafeThaw (V_Pixel vec) = MV_Pixel `liftM` V.basicUnsafeThaw vec@@ -125,9 +125,9 @@   {-# INLINE basicLength #-}   basicUnsafeSlice idx len (V_Pixel vec) = V_Pixel (V.basicUnsafeSlice idx len vec)   {-# INLINE basicUnsafeSlice #-}-  basicUnsafeIndexM (V_Pixel vec) idx = fromElt `liftM` V.basicUnsafeIndexM vec idx+  basicUnsafeIndexM (V_Pixel vec) idx = fromComponents `liftM` V.basicUnsafeIndexM vec idx   {-# INLINE basicUnsafeIndexM #-}   basicUnsafeCopy (MV_Pixel mvec) (V_Pixel vec) = V.basicUnsafeCopy mvec vec   {-# INLINE basicUnsafeCopy #-}-  elemseq (V_Pixel vec) val = V.elemseq vec (toElt val)+  elemseq (V_Pixel vec) val = V.elemseq vec (toComponents val)   {-# INLINE elemseq #-}
src/Graphics/Image/Processing.hs view
@@ -39,7 +39,7 @@ -- -- <<images/frog.jpg>> <<images/frog_eye_grid.png>> ---pixelGrid :: (Array arr cs e, Elevator e) =>+pixelGrid :: Array arr cs e =>              Word8          -- ^ Magnification factor.           -> Image arr cs e -- ^ Source image.           -> Image arr cs e@@ -47,7 +47,7 @@   getNewDims !(m, n) = (1 + m*k, 1 + n*k)   {-# INLINE getNewDims #-}   getNewPx !getPx !(i, j) = if i `mod` k == 0 || j `mod` k == 0-                            then fromDouble $ fromChannel 0.5+                            then broadcastC $ fromDouble 0.5                             else getPx ((i - 1) `div` k, (j - 1) `div` k)   {-# INLINE getNewPx #-} {-# INLINE pixelGrid #-}
src/Graphics/Image/Processing/Binary.hs view
@@ -43,6 +43,7 @@ infixr 2  .||.  + -- | 'Thresholding' contains a convenient set of functions for binary image -- construction, which is done by comparing either a single pixel with every -- pixel in an image or two same size images pointwise. For example:@@ -166,7 +167,8 @@ -- -- <<images/yield.jpg>> <<images/yield_bin.png>> ---thresholdWith :: (Array arr cs e, Array arr Binary Bit) =>+thresholdWith :: (Applicative (Pixel cs), Foldable (Pixel cs),+                  Array arr cs e, Array arr Binary Bit) =>                  Pixel cs (e -> Bool)                  -- ^ Pixel containing a thresholding function per channel.               -> Image arr cs e -- ^ Source image.@@ -177,7 +179,8 @@  -- | Compare two images with an applicative pixel. Works just like -- 'thresholdWith', but on two images.-compareWith :: (Array arr cs e1, Array arr cs e2, Array arr Binary Bit) =>+compareWith :: (Applicative (Pixel cs), Foldable (Pixel cs),+                Array arr cs e1, Array arr cs e2, Array arr Binary Bit) =>                Pixel cs (e1 -> e2 -> Bool)                -- ^ Pixel containing a comparing function per channel.             -> Image arr cs e1 -- ^ First image.@@ -188,8 +191,9 @@   {- $morphology In order to demonstrate how morphological operations work, a-/binary source image/ = __B__ constructed here together with a /structuring element/ =-__S__ will be used in examples that follow.+/binary source image/ = __B__ constructed here together with a /structuring element/+= __S__ will be used in examples that follow. Origin of the structuring+element is always at it's center, eg. @(1,1)@ for the one below.  @ figure :: Image VU Binary Bit@@ -211,7 +215,7 @@                     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],                     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]] struct :: Image VU Binary Bit-struct = fromLists [[0,1],[1,1],[0,1]]+struct = fromLists [[0,1,0],[1,1,0],[0,1,0]] @ -} 
src/Graphics/Image/Processing/Complex.hs view
@@ -10,11 +10,11 @@ -- module Graphics.Image.Processing.Complex (   -- * Rectangular form-  (!+!), realPart', imagPart',+  (!+!), realPartI, imagPartI,   -- * Polar form-  mkPolar', cis', polar', magnitude', phase',+  mkPolarI, cisI, polarI, magnitudeI, phaseI,   -- * Conjugate-  conjugate',+  conjugateI,   -- * Processing   makeFilter, applyFilter,   -- ** Fourier Transform@@ -37,61 +37,61 @@ -- >>> frog !+! frog -- <Image VectorUnboxed RGB (Complex Double): 200x320> ---(!+!) :: (Array arr cs e, Array arr cs (Complex e)) =>+(!+!) :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e)) =>          Image arr cs e -> Image arr cs e -> Image arr cs (Complex e) (!+!) = zipWith (+:) {-# INLINE (!+!) #-}  -- | Extracts the real part of a complex image.-realPart' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) =>+realPartI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) =>              Image arr cs (Complex e) -> Image arr cs e-realPart' = map realPart-{-# INLINE realPart' #-}+realPartI = map realPart+{-# INLINE realPartI #-}  -- | Extracts the imaginary part of a complex image.-imagPart' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) =>+imagPartI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) =>              Image arr cs (Complex e) -> Image arr cs e-imagPart' = map imagPart-{-# INLINE imagPart' #-}+imagPartI = map imagPart+{-# INLINE imagPartI #-}  -- | Form a complex image from polar components of magnitude and phase.-mkPolar' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) =>+mkPolarI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) =>             Image arr cs e -> Image arr cs e -> Image arr cs (Complex e)-mkPolar' = zipWith mkPolar-{-# INLINE mkPolar' #-}+mkPolarI = zipWith mkPolar+{-# INLINE mkPolarI #-} --- | @'cis'' t@ is a complex image with magnitude 1 and phase t (modulo @2*'pi'@).-cis' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) =>+-- | @'cisI' t@ is a complex image with magnitude 1 and phase t (modulo @2*'pi'@).+cisI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) =>         Image arr cs e -> Image arr cs (Complex e)-cis' = map cis-{-# INLINE cis' #-}+cisI = map cis+{-# INLINE cisI #-}  -- | The function @'polar''@ takes a complex image and returns a (magnitude, phase) -- pair of images in canonical form: the magnitude is nonnegative, and the phase -- in the range @(-'pi', 'pi']@; if the magnitude is zero, then so is the phase.-polar' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) =>+polarI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) =>           Image arr cs (Complex e) -> (Image arr cs e, Image arr cs e)-polar' !zImg = (magnitude' zImg, phase' zImg)-{-# INLINE polar' #-}+polarI !zImg = (magnitudeI zImg, phaseI zImg)+{-# INLINE polarI #-}  -- | The nonnegative magnitude of a complex image.-magnitude' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) =>+magnitudeI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) =>               Image arr cs (Complex e) -> Image arr cs e-magnitude' = map magnitude-{-# INLINE magnitude' #-}+magnitudeI = map magnitude+{-# INLINE magnitudeI #-}  -- | The phase of a complex image, in the range @(-'pi', 'pi']@. If the -- magnitude is zero, then so is the phase.-phase' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) =>+phaseI :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e), RealFloat e) =>           Image arr cs (Complex e) -> Image arr cs e-phase' = map phase-{-# INLINE phase' #-}+phaseI = map phase+{-# INLINE phaseI #-}  -- | The conjugate of a complex image.-conjugate' :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) =>+conjugateI :: (Applicative (Pixel cs), Array arr cs (Complex e), RealFloat e) =>               Image arr cs (Complex e) -> Image arr cs (Complex e)-conjugate' = map conjugate-{-# INLINE conjugate' #-}+conjugateI = map conjugate+{-# INLINE conjugateI #-}   -- | Make a filter by using a function that works around a regular @(x, y)@@@ -111,29 +111,11 @@   -- | Apply a filter to an image created by 'makeFilter'.-applyFilter :: (Array arr cs e, Array arr cs (Complex e), RealFloat e) =>+applyFilter :: (Applicative (Pixel cs), Array arr cs e, Array arr cs (Complex e),+                Fractional (Pixel cs (Complex e)), Floating (Pixel cs e), RealFloat e) =>                Image arr cs e -- ^ Source image.             -> Image arr cs e -- ^ Filter.             -> Image arr cs e-applyFilter img filt = realPart' . ifft $ (fft (img !+! 0) * (filt !+! filt))+applyFilter img filt = realPartI . ifft $ (fft (img !+! 0) * (filt !+! filt)) {-# INLINE applyFilter #-} -{--gaussianBandpass :: (ManifestArray arr cs e, RealFloat e) =>-                    Int -> e -> e -> Image arr cs e-gaussianBandpass n center variance = makeFilter (n, n) bandpass where-  gaussian (x, y) = fromChannel $ exp (-(x^(2 :: Int) + y^(2 :: Int)) / (2*variance))-  bandpass (fromIntegral -> y, fromIntegral -> x) = gaussian (x', y')-    where (x' :+ y') = C.mkPolar (mag - center) ph-          (mag, ph) = C.polar (x :+ y)--}          --{--idealBandpass :: (ManifestArray arr cs e, RealFloat e) =>-                 Int -> e -> e -> Image arr cs e-idealBandpass n width center = makeFilter (n, n) bandpass where-  bandpass (fromIntegral -> r, fromIntegral -> c)-    | center <= mag && mag <= (width + center) = 1-    | otherwise = 0-    where mag = C.magnitude (r :+ c)--}
src/Graphics/Image/Processing/Complex/Fourier.hs view
@@ -30,7 +30,9 @@           | Inverse  -- | Fast Fourier Transform-fft :: (Array arr cs (Complex e), RealFloat e) =>+fft :: (Applicative (Pixel cs),+        Array arr cs (Complex e),+        Fractional (Pixel cs (Complex e)), Floating (Pixel cs e), RealFloat e) =>        Image arr cs (Complex e)     -> Image arr cs (Complex e) fft = fft2d Forward@@ -38,7 +40,9 @@   -- | Inverse Fast Fourier Transform-ifft :: (Array arr cs (Complex e), RealFloat e) =>+ifft :: (Applicative (Pixel cs),+         Array arr cs (Complex e),+         Fractional (Pixel cs (Complex e)), Floating (Pixel cs e), RealFloat e) =>         Image arr cs (Complex e)      -> Image arr cs (Complex e) ifft = fft2d Inverse@@ -58,7 +62,9 @@   -- | Compute the DFT of a matrix. Array dimensions must be powers of two else `error`.-fft2d :: (Array arr cs (Complex e), Num e, RealFloat e) =>+fft2d :: (Applicative (Pixel cs),+          Array arr cs (Complex e),+          Fractional (Pixel cs (Complex e)), Floating (Pixel cs e), RealFloat e) =>          Mode       -> Image arr cs (Complex e)       -> Image arr cs (Complex e)@@ -77,7 +83,9 @@ {-# INLINE fft2d #-}  -fftGeneral :: (Array arr cs (Complex e), Num e, RealFloat e) =>+fftGeneral :: (Applicative (Pixel cs),+               Array arr cs (Complex e),+               Floating (Pixel cs e), RealFloat e) =>               Pixel cs e            -> Image arr cs (Complex e)            -> Image arr cs (Complex e)@@ -101,7 +109,8 @@   -- Compute a twiddle factor.-twiddle :: (ColorSpace cs, Floating e) =>+twiddle :: (Applicative (Pixel cs),+            Floating (Pixel cs e)) =>            Pixel cs e         -> Int                  -- index         -> Int                  -- length
src/Graphics/Image/Processing/Convolution.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-} -- | -- Module      : Graphics.Image.Processing.Convolution -- Copyright   : (c) Alexey Kuleshevich 2016@@ -8,19 +9,19 @@ -- Portability : non-portable -- module Graphics.Image.Processing.Convolution (-  convolve, convolveRows, convolveCols,+  convolve, convolveRows, convolveCols   ) where -import Prelude hiding (map)-import qualified Prelude as P (map)-import Graphics.Image.Interface+import Prelude as P+import Graphics.Image.Interface as I+--import Graphics.Image.Interface.Vector.Sparse import Graphics.Image.Processing.Geometric   -convolve'' :: Array arr cs e =>+convolve' :: Array arr cs e =>               Border (Pixel cs e) -> Image arr cs e -> Image arr cs e -> Image arr cs e-convolve'' !border !kernel !img =+convolve' !border !kernel !img =   traverse2 (compute kernel) (compute img) (const . const sz) stencil   where     !(krnM, krnN)     = dims kernel@@ -38,10 +39,35 @@         | otherwise             = let !krnPx = getKrnPx (ki, kj)                                       !imgPx = getPxB getImgPx (ki + ikrnM, kj + jkrnN)                                   in integrate ki (kj + 1) (acc + krnPx * imgPx)-      {-# INLINE integrate #-}     {-# INLINE stencil #-}-{-# INLINE convolve'' #-}+{-# INLINE convolve' #-} +-- convolveSparse :: (Exchangable arr VS, Array arr cs e, Array VS cs e)  =>+--                    Border (Pixel cs e) -> Image arr cs e -> Image arr cs e -> Image arr cs e+-- convolveSparse !border !kernel !img =+--   makeImageWindowed+--     sz+--     ((krnM2, krnN2), (m - krnM2, n - krnN2))+--     (stencil (unsafeIndex imgM))+--     (stencil (borderIndex border imgM))+--   where+--     !imgM = toManifest img+--     !kernel' = exchange VS $ compute kernel+--     -- !kernel' = exchange VS kernel -- deadlock?!?!?+--     !(krnM, krnN) = dims kernel'+--     !krnM2 = krnM `div` 2+--     !krnN2 = krnN `div` 2+--     !sz@(m, n) = dims img+--     stencil getPx !(i, j) = foldIx integral 0 kernel'+--       where+--         integral !acc !(ki, kj) !px = px * (getPx (ki + ikrnM, kj + jkrnN)) + acc+--         {-# INLINE integral #-}+--         !ikrnM = i - krnM2+--         !jkrnN = j - krnN2+--     {-# INLINE stencil #-}+-- {-# INLINE convolveSparse #-}++ -- | Convolution of an image using a kernel. Border resolution technique is required. -- -- Example using <https://en.wikipedia.org/wiki/Sobel_operator Sobel operator>:@@ -53,12 +79,12 @@ -- -- <<images/frogY.jpg>> <<images/frog_sobel.jpg>> ---convolve  :: Array arr cs e =>-             Border (Pixel cs e)   -- ^ Approach to be used near the borders.+convolve :: Array arr cs e =>+             Border (Pixel cs e) -- ^ Approach to be used near the borders.           -> Image arr cs e -- ^ Kernel image.           -> Image arr cs e -- ^ Source image.           -> Image arr cs e-convolve !out = convolve'' out . rotate180+convolve !out = convolve' out . rotate180 {-# INLINE convolve #-}  
src/Graphics/Image/Processing/Geometric.hs view
@@ -51,7 +51,7 @@     (\ !getPx !(i, j) ->         if i `mod` fm == 0 && j `mod` fn == 0           then getPx (i `div` fm, j `div` fn)-          else fromChannel 0)+          else 0) {-# INLINE upsampleF #-}  @@ -209,7 +209,7 @@            -> Image arr cs e -- ^ Source image.            -> Image arr cs e               superimpose !(i0, j0) !imgA !imgB = traverse2 imgB imgA const newPx where-  (m, n) = dims imgA+  !(m, n) = dims imgA   newPx getPxB getPxA (i, j) = let !(i', j') = (i - i0, j - j0) in     if i' >= 0 && j' >= 0 && i' < m && j' < n then getPxA (i', j') else getPxB (i, j) {-# INLINE superimpose #-}@@ -218,7 +218,7 @@  flipUsing :: Array arr cs e =>              ((Int, Int) -> (Int, Int) -> (Int, Int)) -> Image arr cs e -> Image arr cs e-flipUsing getNewIndex !img@(dims -> d) = backpermute d (getNewIndex d) img+flipUsing getNewIndex !img@(dims -> sz) = backpermute sz (getNewIndex sz) img {-# INLINE flipUsing #-}  @@ -290,7 +290,7 @@ -- -- <<images/frog.jpg>> <<images/frog_rotate330.png>> ---rotate :: (Array arr cs e, Elevator e, Interpolation method) =>+rotate :: (Array arr cs e, Interpolation method) =>           method -- ^ Interpolation method to be used        -> Border (Pixel cs e) -- ^ Border handling strategy        -> Double -- ^ Angle in radians@@ -323,7 +323,7 @@ -- -- <<images/frog_resize.jpg>> ---resize :: (Interpolation method, Array arr cs e, Elevator e) =>+resize :: (Interpolation method, Array arr cs e) =>           method -- ^ Interpolation method to be used during scaling.        -> Border (Pixel cs e) -- ^ Border handling strategy        -> (Int, Int)     -- ^ Dimensions of a result image.@@ -343,7 +343,7 @@ -- -- @ scale 'Bilinear' 'Edge' (0.5, 2) frog == resize 'Bilinear' 'Edge' (100, 640) frog @ ---scale :: (Interpolation method, Array arr cs e, Elevator e) =>+scale :: (Interpolation method, Array arr cs e) =>          method -- ^ Interpolation method to be used during scaling.       -> Border (Pixel cs e) -- ^ Border handling strategy       -> (Double, Double) -- ^ Positive scaling factors.
src/Graphics/Image/Processing/Interpolation.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE ViewPatterns #-} -- |@@ -18,7 +19,7 @@ class Interpolation method where    -- | Construct a new pixel by using information from neighboring pixels.-  interpolate :: (Elevator e, Num e, ColorSpace cs) =>+  interpolate :: (Num (Pixel cs e), ColorSpace cs e) =>                  method -- ^ Interpolation method               -> Border (Pixel cs e) -- ^ Border resolution strategy               -> (Int, Int)          -- ^ Image dimensions @m@ rows and @n@ columns.@@ -39,20 +40,20 @@  instance Interpolation Nearest where -  interpolate Nearest border !sz !getPx !(i, j) =+  interpolate Nearest border !sz getPx !(i, j) =     handleBorderIndex border sz getPx (round i, round j)   {-# INLINE interpolate #-}   instance Interpolation Bilinear where -  interpolate Bilinear border !sz !getPx !(i, j) = fi0 + jPx*(fi1-fi0) where+  interpolate Bilinear border !sz getPx !(i, j) = fi0 + jPx*(fi1-fi0) where     getPx' = handleBorderIndex border sz getPx     {-# INLINE getPx' #-}     !(i0, j0) = (floor i, floor j)     !(i1, j1) = (i0 + 1, j0 + 1)-    !iPx = fromDouble $ fromChannel (i - fromIntegral i0)-    !jPx = fromDouble $ fromChannel (j - fromIntegral j0)+    !iPx = broadcastC $ fromDouble (i - fromIntegral i0)+    !jPx = broadcastC $ fromDouble (j - fromIntegral j0)     !f00 = getPx' (i0, j0)     !f10 = getPx' (i1, j0)     !f01 = getPx' (i0, j1) 
src/Graphics/Image/Types.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Graphics.Image.Types -- Copyright   : (c) Alexey Kuleshevich 2016@@ -11,12 +12,77 @@   module Graphics.Image.IO.Formats,   Array, Image, MArray, MImage,   Exchangable, Border(..),-  VU(..), RS(..), RP(..),+  VU(..), VS(..), RSU(..), RPU(..), RSS(..), RPS(..)   ) where   import Graphics.Image.ColorSpace-import Graphics.Image.Interface-import Graphics.Image.Interface.Vector (VU(..))-import Graphics.Image.Interface.Repa (RS(..), RP(..))+import Graphics.Image.Interface as I+import Graphics.Image.Interface.Vector (VU(..), VS(..))+import Graphics.Image.Interface.Repa (RSU(..), RPU(..), RSS(..), RPS(..)) import Graphics.Image.IO.Formats++++{-# RULES+"Image VU Y Double ^ 2/Int" forall (img :: Image VU Y Double). img ^ (2 :: Int) = I.map (^ (2 :: Int)) img+"Image VU Y Double ^ 3/Int" forall (img :: Image VU Y Double). img ^ (3 :: Int) = I.map (^ (3 :: Int)) img+"Image VU Y Double ^ 4/Int" forall (img :: Image VU Y Double). img ^ (4 :: Int) = I.map (^ (4 :: Int)) img+"Image VU Y Double ^ 5/Int" forall (img :: Image VU Y Double). img ^ (5 :: Int) = I.map (^ (5 :: Int)) img+"Image VU Y Double ^ 2/Integer" forall (img :: Image VU Y Double). img ^ (2 :: Integer) = I.map (^ (2 :: Integer)) img+"Image VU Y Double ^ 3/Integer" forall (img :: Image VU Y Double). img ^ (3 :: Integer) = I.map (^ (3 :: Integer)) img+"Image VU Y Double ^ 4/Integer" forall (img :: Image VU Y Double). img ^ (4 :: Integer) = I.map (^ (4 :: Integer)) img+"Image VU Y Double ^ 5/Integer" forall (img :: Image VU Y Double). img ^ (5 :: Integer) = I.map (^ (5 :: Integer)) img+"Image VU Y Double ^ n" forall (img :: Image VU Y Double) n. img ^ n = I.map (^n) img+"Image RPU Y Double ^ 2/Int" forall (img :: Image RPU Y Double). img ^ (2 :: Int) = I.map (^ (2 :: Int)) img+"Image RPU Y Double ^ 3/Int" forall (img :: Image RPU Y Double). img ^ (3 :: Int) = I.map (^ (3 :: Int)) img+"Image RPU Y Double ^ 4/Int" forall (img :: Image RPU Y Double). img ^ (4 :: Int) = I.map (^ (4 :: Int)) img+"Image RPU Y Double ^ 5/Int" forall (img :: Image RPU Y Double). img ^ (5 :: Int) = I.map (^ (5 :: Int)) img+"Image RPU Y Double ^ 2/Integer" forall (img :: Image RPU Y Double). img ^ (2 :: Integer) = I.map (^ (2 :: Integer)) img+"Image RPU Y Double ^ 3/Integer" forall (img :: Image RPU Y Double). img ^ (3 :: Integer) = I.map (^ (3 :: Integer)) img+"Image RPU Y Double ^ 4/Integer" forall (img :: Image RPU Y Double). img ^ (4 :: Integer) = I.map (^ (4 :: Integer)) img+"Image RPU Y Double ^ 5/Integer" forall (img :: Image RPU Y Double). img ^ (5 :: Integer) = I.map (^ (5 :: Integer)) img+"Image RPU Y Double ^ n" forall (img :: Image RPU Y Double) n. img ^ n = I.map (^n) img+"Image RSU Y Double ^ 2/Int" forall (img :: Image RSU Y Double). img ^ (2 :: Int) = I.map (^ (2 :: Int)) img+"Image RSU Y Double ^ 3/Int" forall (img :: Image RSU Y Double). img ^ (3 :: Int) = I.map (^ (3 :: Int)) img+"Image RSU Y Double ^ 4/Int" forall (img :: Image RSU Y Double). img ^ (4 :: Int) = I.map (^ (4 :: Int)) img+"Image RSU Y Double ^ 5/Int" forall (img :: Image RSU Y Double). img ^ (5 :: Int) = I.map (^ (5 :: Int)) img+"Image RSU Y Double ^ 2/Integer" forall (img :: Image RSU Y Double). img ^ (2 :: Integer) = I.map (^ (2 :: Integer)) img+"Image RSU Y Double ^ 3/Integer" forall (img :: Image RSU Y Double). img ^ (3 :: Integer) = I.map (^ (3 :: Integer)) img+"Image RSU Y Double ^ 4/Integer" forall (img :: Image RSU Y Double). img ^ (4 :: Integer) = I.map (^ (4 :: Integer)) img+"Image RSU Y Double ^ 5/Integer" forall (img :: Image RSU Y Double). img ^ (5 :: Integer) = I.map (^ (5 :: Integer)) img+"Image RSU Y Double ^ n" forall (img :: Image RSU Y Double) n. img ^ n = I.map (^n) img+"Image VU RGB Double ^ 2/Int" forall (img :: Image VU RGB Double). img ^ (2 :: Int) = I.map (^ (2 :: Int)) img+"Image VU RGB Double ^ 3/Int" forall (img :: Image VU RGB Double). img ^ (3 :: Int) = I.map (^ (3 :: Int)) img+"Image VU RGB Double ^ 4/Int" forall (img :: Image VU RGB Double). img ^ (4 :: Int) = I.map (^ (4 :: Int)) img+"Image VU RGB Double ^ 5/Int" forall (img :: Image VU RGB Double). img ^ (5 :: Int) = I.map (^ (5 :: Int)) img+"Image VU RGB Double ^ 2/Integer" forall (img :: Image VU RGB Double). img ^ (2 :: Integer) = I.map (^ (2 :: Integer)) img+"Image VU RGB Double ^ 3/Integer" forall (img :: Image VU RGB Double). img ^ (3 :: Integer) = I.map (^ (3 :: Integer)) img+"Image VU RGB Double ^ 4/Integer" forall (img :: Image VU RGB Double). img ^ (4 :: Integer) = I.map (^ (4 :: Integer)) img+"Image VU RGB Double ^ 5/Integer" forall (img :: Image VU RGB Double). img ^ (5 :: Integer) = I.map (^ (5 :: Integer)) img+"Image VU RGB Double ^ n" forall (img :: Image VU RGB Double) n. img ^ n = I.map (^n) img+"Image RPU RGB Double ^ 2/Int" forall (img :: Image RPU RGB Double). img ^ (2 :: Int) = I.map (^ (2 :: Int)) img+"Image RPU RGB Double ^ 3/Int" forall (img :: Image RPU RGB Double). img ^ (3 :: Int) = I.map (^ (3 :: Int)) img+"Image RPU RGB Double ^ 4/Int" forall (img :: Image RPU RGB Double). img ^ (4 :: Int) = I.map (^ (4 :: Int)) img+"Image RPU RGB Double ^ 5/Int" forall (img :: Image RPU RGB Double). img ^ (5 :: Int) = I.map (^ (5 :: Int)) img+"Image RPU RGB Double ^ 2/Integer" forall (img :: Image RPU RGB Double). img ^ (2 :: Integer) = I.map (^ (2 :: Integer)) img+"Image RPU RGB Double ^ 3/Integer" forall (img :: Image RPU RGB Double). img ^ (3 :: Integer) = I.map (^ (3 :: Integer)) img+"Image RPU RGB Double ^ 4/Integer" forall (img :: Image RPU RGB Double). img ^ (4 :: Integer) = I.map (^ (4 :: Integer)) img+"Image RPU RGB Double ^ 5/Integer" forall (img :: Image RPU RGB Double). img ^ (5 :: Integer) = I.map (^ (5 :: Integer)) img+"Image RPU RGB Double ^ n" forall (img :: Image RPU RGB Double) n. img ^ n = I.map (^n) img+"Image RSU RGB Double ^ 2/Int" forall (img :: Image RSU RGB Double). img ^ (2 :: Int) = I.map (^ (2 :: Int)) img+"Image RSU RGB Double ^ 3/Int" forall (img :: Image RSU RGB Double). img ^ (3 :: Int) = I.map (^ (3 :: Int)) img+"Image RSU RGB Double ^ 4/Int" forall (img :: Image RSU RGB Double). img ^ (4 :: Int) = I.map (^ (4 :: Int)) img+"Image RSU RGB Double ^ 5/Int" forall (img :: Image RSU RGB Double). img ^ (5 :: Int) = I.map (^ (5 :: Int)) img+"Image RSU RGB Double ^ 2/Integer" forall (img :: Image RSU RGB Double). img ^ (2 :: Integer) = I.map (^ (2 :: Integer)) img+"Image RSU RGB Double ^ 3/Integer" forall (img :: Image RSU RGB Double). img ^ (3 :: Integer) = I.map (^ (3 :: Integer)) img+"Image RSU RGB Double ^ 4/Integer" forall (img :: Image RSU RGB Double). img ^ (4 :: Integer) = I.map (^ (4 :: Integer)) img+"Image RSU RGB Double ^ 5/Integer" forall (img :: Image RSU RGB Double). img ^ (5 :: Integer) = I.map (^ (5 :: Integer)) img+"Image RSU RGB Double ^ n" forall (img :: Image RSU RGB Double) n. img ^ n = I.map (^n) img+ #-}++++--{-# RULES+--"I.map/id" forall img. I.map id img = img+-- #-}
tests/Graphics/Image/ColorSpaceSpec.hs view
@@ -30,11 +30,11 @@     II.mapM (const arbitrary) $ I.makeImage (m, n) (const $ PixelGray (0 :: Double))    -prop_ToFromElt :: (ColorSpace cs, Eq (Pixel cs e)) =>-                  Pixel cs e -> Bool-prop_ToFromElt px = px == fromElt (toElt px)+prop_ToFromComponents :: (ColorSpace cs e, Eq (Pixel cs e)) =>+                         Pixel cs e -> Bool+prop_ToFromComponents px = px == fromComponents (toComponents px)   spec :: Spec spec = describe "ColorSpace" $ do-  it "RGBElt" $ property (prop_ToFromElt :: Pixel RGB Int -> Bool)+  it "RGBComponents" $ property (prop_ToFromComponents :: Pixel RGB Double -> Bool)
tests/Graphics/Image/Interface/VectorSpec.hs view
@@ -4,22 +4,21 @@ import Test.Hspec import Test.QuickCheck -import qualified Graphics.Image as IM-import qualified Graphics.Image.Interface.Vector as IV-import Graphics.Image.Types+import Graphics.Image as I+import Graphics.Image.Interface.Vector  import Graphics.Image.InterfaceSpec ()  prop_fromToIx :: Positive Int -> (NonNegative Int, NonNegative Int) -> Bool prop_fromToIx (Positive n) (NonNegative i, NonNegative j) =-  (i, j `mod` n) == IV.toIx n (IV.fromIx n (i, j `mod` n))+  (i, j `mod` n) == toIx n (fromIx n (i, j `mod` n))  prop_toFromIx :: Positive Int -> NonNegative Int -> Bool-prop_toFromIx (Positive n) (NonNegative k) = k == IV.fromIx n (IV.toIx n k)+prop_toFromIx (Positive n) (NonNegative k) = k == fromIx n (toIx n k)  prop_toFromVector   :: Image VU Y Word8 -> Bool-prop_toFromVector img = img == IV.fromUnboxedVector (IM.dims img) (IV.toUnboxedVector img)+prop_toFromVector img = img == fromUnboxedVector (dims img) (toUnboxedVector img)  spec :: Spec spec = do
tests/Graphics/Image/InterfaceSpec.hs view
@@ -10,6 +10,7 @@   , Identical (..)   ) where +import Prelude as P #if MIN_VERSION_base(4,8,0) import Data.Typeable (Typeable, typeOf) #else@@ -18,10 +19,8 @@ import Test.Hspec import Test.QuickCheck -import qualified Graphics.Image as IM-import qualified Graphics.Image.Interface as I-import Graphics.Image.Types-import Graphics.Image.Processing+import Graphics.Image as I+import Graphics.Image.Interface as I   data Identical arr1 arr2 cs e =@@ -71,16 +70,15 @@   instance Arbitrary px => Arbitrary (Border px) where-  arbitrary = do-    methodIx <- arbitrary-    case methodIx `mod` 5 :: Int of-      0 -> Fill <$> arbitrary-      1 -> return Wrap-      2 -> return Edge-      3 -> return Reflect-      4 -> return Continue-      _ -> error "Unknown method"-+  arbitrary =+    oneof+      [ Fill <$> arbitrary+      , return Wrap+      , return Edge+      , return Reflect+      , return Continue+      ]+        #if MIN_VERSION_base(4,8,0) instance (Typeable a, Typeable b) => Show (a -> b) where@@ -107,7 +105,7 @@ prop_borderIndex border img (Positive i, Positive j) =   I.borderIndex border img (iOut, jOut) == I.index bigImg (iBig, jBig)   where-    bigImg = foldr1 topToBottom $ map (foldr1 leftToRight) imgs+    bigImg = foldr1 topToBottom $ P.map (foldr1 leftToRight) imgs     (m, n) = I.dims img     (iBig, jBig) = (i `mod` (3 * m), j `mod` (3 * n))     (iOut, jOut) = (iBig - m, jBig - n)@@ -163,69 +161,65 @@     newPx getPx (i, j) = getPx ((i - dm) `mod` m, (j - dn) `mod` n)  -prop_toFormLists :: (Array arr Y Word8, MArray arr Y Word8) => arr -> Image arr Y Word8 -> Bool-prop_toFormLists _ img = img == I.fromLists (IM.toLists img)-- prop_sameDims :: Array arr Y Word8 => arr -> Identical VU arr Y Word8 -> Bool prop_sameDims _ (Identical img1 img2) = I.dims img1 == I.dims img2  prop_sameImage-  :: (Exchangable arr RS, Array arr Y Word8)-  => arr -> Identical VU arr Y Word8 -> Bool-prop_sameImage _ (Identical img1 img2) = I.exchange RS img1 == I.exchange RS img2+  :: (Exchangable arr VU, Array arr RGB Word8)+  => arr -> Identical VU arr RGB Word8 -> Bool+prop_sameImage _ (Identical img1 img2) = img1 == I.exchange VU img2  prop_sameMap-  :: (Exchangable arr RS, Array arr Y Word8)+  :: (Exchangable arr RSU, Array arr Y Word8)   => arr -> (Pixel Y Word8 -> Pixel Y Word8) -> Identical VU arr Y Word8 -> Bool prop_sameMap _ f (Identical img1 img2) =-  I.exchange RS (I.map f img1) == I.exchange RS (I.map f img2)+  I.exchange RSU (I.map f img1) == I.exchange RSU (I.map f img2)  prop_sameImap-  :: (Exchangable arr RP, Array arr Y Word8)+  :: (Exchangable arr RPU, Array arr Y Word8)   => arr -> ((Int, Int) -> Pixel Y Word8 -> Pixel Y Word8) -> Identical VU arr Y Word8 -> Bool prop_sameImap _ f (Identical img1 img2) =-  I.exchange RP (I.imap f img1) == I.exchange RP (I.imap f img2)+  I.exchange RPU (I.imap f img1) == I.exchange RPU (I.imap f img2)   prop_sameZipWith-  :: (Exchangable arr RP, Array arr Y Word8)+  :: (Exchangable arr RPU, Array arr Y Word8)   => arr   -> (Pixel Y Word8 -> Pixel Y Word8)   -> (Pixel Y Word8 -> Pixel Y Word8 -> Pixel Y Word8)   -> Identical VU arr Y Word8   -> Bool prop_sameZipWith _ g f (Identical img1 img2) =-  I.exchange RP (I.zipWith f img1 img1') ==-  I.exchange RP (I.zipWith f img2 img2')+  I.exchange RPU (I.zipWith f img1 img1') ==+  I.exchange RPU (I.zipWith f img2 img2')   where     img1' = I.map g img1     img2' = I.map g img2  prop_sameIZipWith-  :: (Exchangable arr RP, Array arr Y Word8)+  :: (Exchangable arr RPU, Array arr Y Word8)   => arr   -> (Pixel Y Word8 -> Pixel Y Word8)   -> ((Int, Int) -> Pixel Y Word8 -> Pixel Y Word8 -> Pixel Y Word8)   -> Identical VU arr Y Word8   -> Bool prop_sameIZipWith _ g f (Identical img1 img2) =-  I.exchange RP (I.izipWith f img1 img1') ==-  I.exchange RP (I.izipWith f img2 img2')+  I.exchange RPU (I.izipWith f img1 img1') ==+  I.exchange RPU (I.izipWith f img2 img2')   where     img1' = I.map g img1     img2' = I.map g img2  prop_sameTraverse-  :: (Exchangable arr RS, Array arr Y Word8)+  :: (Exchangable arr RSU, Array arr Y Word8)   => arr   -> ((Int, Int) -> (Positive (Small Int), Positive (Small Int)))   -> ((Int, Int) -> Pixel Y Word8 -> Pixel Y Word8)   -> Identical VU arr Y Word8   -> Bool prop_sameTraverse _ g f (Identical img1 img2) =-  I.exchange RS (I.traverse img1 (g' . g) f') ==-  I.exchange RS (I.traverse img2 (g' . g) f')+  I.exchange RSU (I.traverse img1 (g' . g) f') ==+  I.exchange RSU (I.traverse img2 (g' . g) f')   where     g' (Positive (Small i), Positive (Small j)) = (i, j)     f' getPx ix@(i, j) = f ix (getPx (i `mod` m, j `mod` n))@@ -233,7 +227,7 @@   prop_sameTraverse2-  :: (Exchangable arr RS, Array arr Y Word8)+  :: (Exchangable arr RSU, Array arr Y Word8)   => arr   -> ((Int, Int) -> (Int, Int) -> (Positive (Small Int), Positive (Small Int)))   -> ((Int, Int) -> Pixel Y Word8 -> Pixel Y Word8 -> Pixel Y Word8)@@ -241,8 +235,8 @@   -> Identical VU arr Y Word8   -> Bool prop_sameTraverse2 _ g f (Identical img1a img2a) (Identical img1b img2b) =-  I.exchange RS (I.traverse2 img1a img1b g' f') ==-  I.exchange RS (I.traverse2 img2a img2b g' f')+  I.exchange RSU (I.traverse2 img1a img1b g' f') ==+  I.exchange RSU (I.traverse2 img2a img2b g' f')   where     g' dimsA dimsB =       case g dimsA dimsB of@@ -254,52 +248,66 @@   prop_sameTranspose-  :: (Exchangable arr RS, Array arr Y Word8)+  :: (Exchangable arr RSU, Array arr Y Word8)   => arr   -> Identical VU arr Y Word8   -> Bool prop_sameTranspose _ (Identical img1 img2) =-  I.exchange RS (I.transpose img1) == I.exchange RS (I.transpose img2)+  I.exchange RSU (I.transpose img1) == I.exchange RSU (I.transpose img2)   prop_sameBackpermute-  :: (Exchangable arr RP, Array arr Y Word8)+  :: (Exchangable arr RPU, Array arr Y Word8)   => arr   -> (Positive (Small Int), Positive (Small Int))   -> ((Int, Int) -> (Int, Int))   -> Identical VU arr Y Word8   -> Bool prop_sameBackpermute _ (Positive (Small m), Positive (Small n)) f (Identical img1 img2) =-  I.exchange RP (I.backpermute (m, n) (f' . f) img1) ==-  I.exchange RP (I.backpermute (m, n) (f' . f) img2)+  I.exchange RPU (I.backpermute (m, n) (f' . f) img1) ==+  I.exchange RPU (I.backpermute (m, n) (f' . f) img2)   where     (m', n') = I.dims img1     f' (i, j) = (i `mod` m', j `mod` n')  +prop_toFormLists :: (Array arr Y Word8, MArray arr Y Word8) => arr -> Image arr Y Word8 -> Bool+prop_toFormLists _ img = img == I.fromLists (I.toLists img)++ spec :: Spec spec = do   describe "Interface Properties" $ do     it "borderIndex" $ property prop_borderIndex     it "toFormLists" $ property $ prop_toFormLists VU   describe "Representation Properties" $ do-    it "sameDims RS" $ property $ prop_sameDims RS-    it "sameDims RP" $ property $ prop_sameDims RP-    it "sameImage RS" $ property $ prop_sameImage RS-    it "sameImage RP" $ property $ prop_sameImage RP-    it "sameMap RS" $ property $ prop_sameMap RS-    it "sameMap RP" $ property $ prop_sameMap RP-    it "sameImap RS" $ property $ prop_sameImap RS-    it "sameImap RP" $ property $ prop_sameImap RP-    it "sameZipWith RS" $ property $ prop_sameZipWith RS-    it "sameZipWith RP" $ property $ prop_sameZipWith RP-    it "sameIZipWith RS" $ property $ prop_sameIZipWith RS-    it "sameIZipWith RP" $ property $ prop_sameIZipWith RP-    it "sameTraverse RS" $ property $ prop_sameTraverse RS-    it "sameTraverse RP" $ property $ prop_sameTraverse RP-    it "sameTraverse2 RS" $ property $ prop_sameTraverse2 RS-    it "sameTraverse2 RP" $ property $ prop_sameTraverse2 RP-    it "sameTranspose RS" $ property $ prop_sameTranspose RS-    it "sameTranspose RP" $ property $ prop_sameTranspose RP-    it "sameBackpermute RS" $ property $ prop_sameBackpermute RS-    it "sameBackpermute RP" $ property $ prop_sameBackpermute RP+    it "sameDims VS" $ property $ prop_sameDims VS+    it "sameDims RSU" $ property $ prop_sameDims RSU+    it "sameDims RPU" $ property $ prop_sameDims RPU+    it "sameImage VS" $ property $ prop_sameImage VS+    it "sameImage RSU" $ property $ prop_sameImage RSU+    it "sameImage RPU" $ property $ prop_sameImage RPU+    --it "sameMap VS" $ property $ prop_sameMap VS+    it "sameMap RSU" $ property $ prop_sameMap RSU+    it "sameMap RPU" $ property $ prop_sameMap RPU+    --it "sameImap VS" $ property $ prop_sameImap VS+    it "sameImap RSU" $ property $ prop_sameImap RSU+    it "sameImap RPU" $ property $ prop_sameImap RPU+    --it "sameZipWith VS" $ property $ prop_sameZipWith VS+    it "sameZipWith RSU" $ property $ prop_sameZipWith RSU+    it "sameZipWith RPU" $ property $ prop_sameZipWith RPU+    --it "sameIZipWith VS" $ property $ prop_sameIZipWith VS+    it "sameIZipWith RSU" $ property $ prop_sameIZipWith RSU+    it "sameIZipWith RPU" $ property $ prop_sameIZipWith RPU+    --it "sameTraverse VS" $ property $ prop_sameTraverse VS+    it "sameTraverse RSU" $ property $ prop_sameTraverse RSU+    it "sameTraverse RPU" $ property $ prop_sameTraverse RPU+    --it "sameTraverse2 VS" $ property $ prop_sameTraverse2 VS+    it "sameTraverse2 RSU" $ property $ prop_sameTraverse2 RSU+    it "sameTraverse2 RPU" $ property $ prop_sameTraverse2 RPU+    --it "sameTranspose VS" $ property $ prop_sameTranspose VS+    it "sameTranspose RSU" $ property $ prop_sameTranspose RSU+    it "sameTranspose RPU" $ property $ prop_sameTranspose RPU+    --it "sameBackpermute VS" $ property $ prop_sameBackpermute VS+    it "sameBackpermute RSU" $ property $ prop_sameBackpermute RSU+    it "sameBackpermute RPU" $ property $ prop_sameBackpermute RPU
+ tests/Graphics/Image/Processing/BinarySpec.hs view
@@ -0,0 +1,132 @@+{-# LANGUAGE FlexibleContexts #-}+module Graphics.Image.Processing.BinarySpec (spec) where++import Test.Hspec++import Graphics.Image as I+++figure :: Image VU Binary Bit+figure =+  fromLists+    [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0]+    , [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    ]+struct :: Image VU Binary Bit+struct = fromLists [[0,1,0],[1,1,0],[0,1,0]]+++eroded :: Image VU Binary Bit+eroded =+  fromLists+    [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    ]++dialated :: Image VU Binary Bit+dialated =+  fromLists+    [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0]+    , [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0]+    , [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0]+    , [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0]+    , [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0]+    , [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0]+    , [0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    ]+++opened :: Image VU Binary Bit+opened =+  fromLists+    [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    ]+++closed :: Image VU Binary Bit+closed =+  fromLists+    [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]+    ]++++spec :: Spec+spec = do+  describe "Morphology Spec" $+    do it "erode" (erode struct figure `shouldBe` eroded)+       it "dialate" (dialate struct figure `shouldBe` dialated)+       it "open" (open struct figure `shouldBe` opened)+       it "close" (close struct figure `shouldBe` closed)       
tests/Graphics/Image/ProcessingSpec.hs view
@@ -9,6 +9,7 @@ import Graphics.Image.Processing  import Graphics.Image.InterfaceSpec (translateWrap, dummyImage10x20)+--import Graphics.Image.Processing.BinarySpec  data Interpol   = I1 Nearest