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 +18/−0
- README.md +3/−3
- benchmarks/Canny.hs +161/−0
- benchmarks/Interface.hs +0/−75
- hip.cabal +52/−6
- images/figure_close.png binary
- images/figure_dialate.png binary
- images/figure_erode.png binary
- images/figure_open.png binary
- images/struct.png binary
- src/Graphics/Image.hs +75/−47
- src/Graphics/Image/ColorSpace.hs +169/−138
- src/Graphics/Image/ColorSpace/Binary.hs +93/−38
- src/Graphics/Image/ColorSpace/CMYK.hs +273/−97
- src/Graphics/Image/ColorSpace/Complex.hs +12/−10
- src/Graphics/Image/ColorSpace/Gray.hs +143/−59
- src/Graphics/Image/ColorSpace/HSI.hs +273/−104
- src/Graphics/Image/ColorSpace/Luma.hs +251/−92
- src/Graphics/Image/ColorSpace/RGB.hs +431/−89
- src/Graphics/Image/ColorSpace/YCbCr.hs +272/−96
- src/Graphics/Image/IO.hs +11/−11
- src/Graphics/Image/IO/Formats/JuicyPixels.hs +375/−400
- src/Graphics/Image/IO/Formats/Netpbm.hs +36/−34
- src/Graphics/Image/IO/Histogram.hs +79/−10
- src/Graphics/Image/Interface.hs +129/−147
- src/Graphics/Image/Interface/Repa.hs +59/−38
- src/Graphics/Image/Interface/Repa/Generic.hs +494/−0
- src/Graphics/Image/Interface/Repa/Helpers.hs +39/−0
- src/Graphics/Image/Interface/Repa/Internal.hs +0/−490
- src/Graphics/Image/Interface/Repa/Storable.hs +275/−0
- src/Graphics/Image/Interface/Repa/Unboxed.hs +243/−0
- src/Graphics/Image/Interface/Vector.hs +17/−48
- src/Graphics/Image/Interface/Vector/Generic.hs +292/−0
- src/Graphics/Image/Interface/Vector/Storable.hs +196/−0
- src/Graphics/Image/Interface/Vector/Unboxed.hs +68/−154
- src/Graphics/Image/Interface/Vector/Unboxing.hs +11/−11
- src/Graphics/Image/Processing.hs +2/−2
- src/Graphics/Image/Processing/Binary.hs +9/−5
- src/Graphics/Image/Processing/Complex.hs +32/−50
- src/Graphics/Image/Processing/Complex/Fourier.hs +14/−5
- src/Graphics/Image/Processing/Convolution.hs +37/−11
- src/Graphics/Image/Processing/Geometric.hs +6/−6
- src/Graphics/Image/Processing/Interpolation.hs +6/−5
- src/Graphics/Image/Types.hs +70/−4
- tests/Graphics/Image/ColorSpaceSpec.hs +4/−4
- tests/Graphics/Image/Interface/VectorSpec.hs +5/−6
- tests/Graphics/Image/InterfaceSpec.hs +71/−63
- tests/Graphics/Image/Processing/BinarySpec.hs +132/−0
- tests/Graphics/Image/ProcessingSpec.hs +1/−0
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