hip 1.5.5.0 → 1.5.6.0
raw patch · 4 files changed
+116/−17 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Graphics.Image.Processing: Bicubic :: Double -> Bicubic
+ Graphics.Image.Processing: newtype Bicubic
Files
- CHANGELOG.md +5/−0
- hip.cabal +1/−1
- src/Graphics/Image/Processing/Interpolation.hs +90/−3
- tests/Graphics/Image/ProcessingSpec.hs +20/−13
CHANGELOG.md view
@@ -1,3 +1,8 @@+1.5.6.0+=======++* Addition of Bicubic interpolation (Thanks to @kirisaki)+ 1.5.5.0 =======
hip.cabal view
@@ -1,5 +1,5 @@ Name: hip-Version: 1.5.5.0+Version: 1.5.6.0 License: BSD3 License-File: LICENSE Author: Alexey Kuleshevich
src/Graphics/Image/Processing/Interpolation.hs view
@@ -10,7 +10,7 @@ -- Portability : non-portable -- module Graphics.Image.Processing.Interpolation (- Interpolation(..), Nearest(..), Bilinear(..)+ Interpolation(..), Nearest(..), Bilinear(..), Bicubic(..) ) where import Graphics.Image.Interface@@ -38,16 +38,21 @@ data Bilinear = Bilinear deriving Show +-- | Bicubic interpolation method.+-- The parameter is usually set from -0.5 to -1.0.+newtype Bicubic = Bicubic Double deriving Show++ 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)@@ -60,4 +65,86 @@ !f11 = getPx' (i1, j1) !fi0 = f00 + iPx*(f10-f00) !fi1 = f01 + iPx*(f11-f01)+ {-# INLINE interpolate #-}+++instance Interpolation Bicubic where++ interpolate (Bicubic a) border !sz getPx (i, j) =+ ( f00 + f10 + f20 + f30+ + f01 + f11 + f21 + f31+ + f02 + f12 + f22 + f32+ + f03 + f13 + f23 + f33 ) * promote (fromDouble (1 / w))+ where+ getPx' = handleBorderIndex border sz getPx+ {-# INLINE getPx' #-}+ distX x = fromIntegral x - i+ {-# INLINE distX #-}+ distY y = fromIntegral y - j+ {-# INLINE distY #-}+ weight x+ | x' <= 1 = ((a + 2) * x' - (a + 3)) * x2' + 1+ | x' < 2 = a * ((x2' - 5 * x' + 8) * x' - 4)+ | otherwise = 0+ where x' = abs x+ x2' = x' * x'+ {-# INLINE weight #-}+ !(i0, j0) = (i1 - 1, j1 - 1)+ !(i1, j1) = (floor i, floor j)+ !(i2, j2) = (i1 + 1, j1 + 1)+ !(i3, j3) = (i1 + 2, j1 + 2)++ !weightX0 = weight (distX i0)+ !weightX1 = weight (distX i1)+ !weightX2 = weight (distX i2)+ !weightX3 = weight (distX i3)+ !weightY0 = weight (distY j0)+ !weightY1 = weight (distY j1)+ !weightY2 = weight (distY j2)+ !weightY3 = weight (distY j3)++ !weightX0Y0 = weightX0 * weightY0+ !weightX1Y0 = weightX1 * weightY0+ !weightX2Y0 = weightX2 * weightY0+ !weightX3Y0 = weightX3 * weightY0++ !weightX0Y1 = weightX0 * weightY1+ !weightX1Y1 = weightX1 * weightY1+ !weightX2Y1 = weightX2 * weightY1+ !weightX3Y1 = weightX3 * weightY1++ !weightX0Y2 = weightX0 * weightY2+ !weightX1Y2 = weightX1 * weightY2+ !weightX2Y2 = weightX2 * weightY2+ !weightX3Y2 = weightX3 * weightY2++ !weightX0Y3 = weightX0 * weightY3+ !weightX1Y3 = weightX1 * weightY3+ !weightX2Y3 = weightX2 * weightY3+ !weightX3Y3 = weightX3 * weightY3++ !f00 = getPx' (i0, j0) * promote (fromDouble weightX0Y0)+ !f10 = getPx' (i1, j0) * promote (fromDouble weightX1Y0)+ !f20 = getPx' (i2, j0) * promote (fromDouble weightX2Y0)+ !f30 = getPx' (i3, j0) * promote (fromDouble weightX3Y0)++ !f01 = getPx' (i0, j1) * promote (fromDouble weightX0Y1)+ !f11 = getPx' (i1, j1) * promote (fromDouble weightX1Y1)+ !f21 = getPx' (i2, j1) * promote (fromDouble weightX2Y1)+ !f31 = getPx' (i3, j1) * promote (fromDouble weightX3Y1)++ !f02 = getPx' (i0, j2) * promote (fromDouble weightX0Y2)+ !f12 = getPx' (i1, j2) * promote (fromDouble weightX1Y2)+ !f22 = getPx' (i2, j2) * promote (fromDouble weightX2Y2)+ !f32 = getPx' (i3, j2) * promote (fromDouble weightX3Y2)++ !f03 = getPx' (i0, j3) * promote (fromDouble weightX0Y3)+ !f13 = getPx' (i1, j3) * promote (fromDouble weightX1Y3)+ !f23 = getPx' (i2, j3) * promote (fromDouble weightX2Y3)+ !f33 = getPx' (i3, j3) * promote (fromDouble weightX3Y3)++ !w = weightX0Y0 + weightX1Y0 + weightX2Y0 + weightX3Y0+ + weightX0Y1 + weightX1Y1 + weightX2Y1 + weightX3Y1+ + weightX0Y2 + weightX1Y2 + weightX2Y2 + weightX3Y2+ + weightX0Y3 + weightX1Y3 + weightX2Y3 + weightX3Y3 {-# INLINE interpolate #-}
tests/Graphics/Image/ProcessingSpec.hs view
@@ -13,17 +13,20 @@ data Interpol = I1 Nearest | I2 Bilinear+ | I3 Bicubic instance Show Interpol where show (I1 i) = "I1 " ++ show i show (I2 i) = "I2 " ++ show i+ show (I3 i) = "I3 " ++ show i instance Arbitrary Interpol where arbitrary = do ix <- arbitrary- case ix `mod` (2 :: Int) of+ case ix `mod` (3 :: Int) of 0 -> return $ I1 Nearest 1 -> return $ I2 Bilinear+ 2 -> I3 . Bicubic <$> pure (-1) -- choose (-1, -0.5) _ -> error $ "Unknown interpolation: " ++ show ix @@ -71,21 +74,25 @@ rotate90 (leftToRight img $ rotate180 img) -prop_rotate90 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Bool-prop_rotate90 (I1 i) border img = rotate90 img == rotate i border (pi/2) img-prop_rotate90 (I2 i) border img = rotate90 img == rotate i border (pi/2) img+prop_rotate90 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Property+prop_rotate90 (I1 i) border img = rotate90 img === rotate i border (pi/2) img+prop_rotate90 (I2 i) border img = rotate90 img === rotate i border (pi/2) img+prop_rotate90 (I3 i) border img = rotate90 img === rotate i border (pi/2) img -prop_rotate180 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Bool-prop_rotate180 (I1 i) border img = rotate180 img == rotate i border pi img-prop_rotate180 (I2 i) border img = rotate180 img == rotate i border pi img+prop_rotate180 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Property+prop_rotate180 (I1 i) border img = rotate180 img === rotate i border pi img+prop_rotate180 (I2 i) border img = rotate180 img === rotate i border pi img+prop_rotate180 (I3 i) border img = rotate180 img === rotate i border pi img -prop_rotate270 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Bool-prop_rotate270 (I1 i) border img = rotate270 img == rotate i border (3*pi/2) img-prop_rotate270 (I2 i) border img = rotate270 img == rotate i border (3*pi/2) img+prop_rotate270 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Property+prop_rotate270 (I1 i) border img = rotate270 img === rotate i border (3*pi/2) img+prop_rotate270 (I2 i) border img = rotate270 img === rotate i border (3*pi/2) img+prop_rotate270 (I3 i) border img = rotate270 img === rotate i border (3*pi/2) img -prop_rotate360 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Bool-prop_rotate360 (I1 i) border img = (rotate270 . rotate90) img == rotate i border (2*pi) img-prop_rotate360 (I2 i) border img = (rotate270 . rotate90) img == rotate i border (2*pi) img+prop_rotate360 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Property+prop_rotate360 (I1 i) border img = (rotate270 . rotate90) img === rotate i border (2*pi) img+prop_rotate360 (I2 i) border img = (rotate270 . rotate90) img === rotate i border (2*pi) img+prop_rotate360 (I3 i) border img = (rotate270 . rotate90) img === rotate i border (2*pi) img struct :: Image VS X Bit