Skip to content

Commit 3f8a39a

Browse files
committed
Fix Bicubic interpolation. Ensure tests are passing. Bump up the version and update changelog
1 parent 9debfc3 commit 3f8a39a

File tree

4 files changed

+103
-98
lines changed

4 files changed

+103
-98
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
1.5.6.0
2+
=======
3+
4+
* Addition of Bicubic interpolation (Thanks to @kirisaki)
5+
16
1.5.5.0
27
=======
38

hip.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Name: hip
2-
Version: 1.5.5.0
2+
Version: 1.5.6.0
33
License: BSD3
44
License-File: LICENSE
55
Author: Alexey Kuleshevich

src/Graphics/Image/Processing/Interpolation.hs

Lines changed: 80 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,19 @@ data Bilinear = Bilinear deriving Show
4040

4141
-- | Bicubic interpolation method.
4242
-- The parameter is usually set from -0.5 to -1.0.
43-
data Bicubic = Bicubic Double deriving Show
43+
newtype Bicubic = Bicubic Double deriving Show
4444

4545

4646
instance Interpolation Nearest where
4747

48-
interpolate Nearest border !sz getPx !(i, j) =
48+
interpolate Nearest border !sz getPx (i, j) =
4949
handleBorderIndex border sz getPx (round i, round j)
5050
{-# INLINE interpolate #-}
5151

5252

5353
instance Interpolation Bilinear where
5454

55-
interpolate Bilinear border !sz getPx !(i, j) = fi0 + jPx*(fi1-fi0) where
55+
interpolate Bilinear border !sz getPx (i, j) = fi0 + jPx*(fi1-fi0) where
5656
getPx' = handleBorderIndex border sz getPx
5757
{-# INLINE getPx' #-}
5858
!(i0, j0) = (floor i, floor j)
@@ -70,81 +70,81 @@ instance Interpolation Bilinear where
7070

7171
instance Interpolation Bicubic where
7272

73-
interpolate (Bicubic a) border !sz getPx !(i, j) = ( f00 + f10 + f20 + f30
74-
+ f01 + f11 + f21 + f31
75-
+ f02 + f12 + f22 + f32
76-
+ f03 + f13 + f23 + f33
77-
) * w where
78-
getPx' = handleBorderIndex border sz getPx
79-
{-# INLINE getPx' #-}
80-
distX x = fromIntegral x - i
81-
{-# INLINE distX #-}
82-
distY y = fromIntegral y - j
83-
{-# INLINE distY #-}
84-
weight x
85-
| x' <= 1 = (a + 2) * x' ** 3 - (a + 3) * x' ** 2 + 1
86-
| x' < 2 = a * x' ** 3 - 5 * a * x' ** 2 + 8 * a * x' - 4 * a
87-
| otherwise = 0
88-
where x' = abs x
89-
{-# INLINE weight #-}
90-
!(i1, j1) = (floor i, floor j)
91-
!(i0, j0) = (i1 - 1, j1 - 1)
92-
!(i2, j2) = (i1 + 1, j1 + 1)
93-
!(i3, j3) = (i1 + 2, j1 + 2)
94-
95-
!weightX0 = weight (distX i0)
96-
!weightY0 = weight (distY i0)
97-
!weightX1 = weight (distX i1)
98-
!weightY1 = weight (distY i1)
99-
!weightX2 = weight (distX i2)
100-
!weightY2 = weight (distY i2)
101-
!weightX3 = weight (distX i3)
102-
!weightY3 = weight (distY i3)
103-
104-
!weightX0Y0 = weightX0 * weightY0
105-
!weightX1Y0 = weightX1 * weightY0
106-
!weightX2Y0 = weightX2 * weightY0
107-
!weightX3Y0 = weightX3 * weightY0
108-
109-
!weightX0Y1 = weightX0 * weightY1
110-
!weightX1Y1 = weightX1 * weightY1
111-
!weightX2Y1 = weightX2 * weightY1
112-
!weightX3Y1 = weightX3 * weightY1
113-
114-
!weightX0Y2 = weightX0 * weightY2
115-
!weightX1Y2 = weightX1 * weightY2
116-
!weightX2Y2 = weightX2 * weightY2
117-
!weightX3Y2 = weightX3 * weightY2
118-
119-
!weightX0Y3 = weightX0 * weightY3
120-
!weightX1Y3 = weightX1 * weightY3
121-
!weightX2Y3 = weightX2 * weightY3
122-
!weightX3Y3 = weightX3 * weightY3
123-
124-
!f00 = getPx' (i0, j0) * promote (fromDouble weightX0Y0)
125-
!f10 = getPx' (i1, j0) * promote (fromDouble weightX1Y0)
126-
!f20 = getPx' (i2, j0) * promote (fromDouble weightX2Y0)
127-
!f30 = getPx' (i3, j0) * promote (fromDouble weightX3Y0)
128-
129-
!f01 = getPx' (i0, j1) * promote (fromDouble weightX0Y1)
130-
!f11 = getPx' (i1, j1) * promote (fromDouble weightX1Y1)
131-
!f21 = getPx' (i2, j1) * promote (fromDouble weightX2Y1)
132-
!f31 = getPx' (i3, j1) * promote (fromDouble weightX3Y1)
133-
134-
!f02 = getPx' (i0, j2) * promote (fromDouble weightX0Y2)
135-
!f12 = getPx' (i1, j2) * promote (fromDouble weightX1Y2)
136-
!f22 = getPx' (i2, j2) * promote (fromDouble weightX2Y2)
137-
!f32 = getPx' (i3, j2) * promote (fromDouble weightX3Y2)
138-
139-
!f03 = getPx' (i0, j3) * promote (fromDouble weightX0Y3)
140-
!f13 = getPx' (i1, j3) * promote (fromDouble weightX1Y3)
141-
!f23 = getPx' (i2, j3) * promote (fromDouble weightX2Y3)
142-
!f33 = getPx' (i3, j3) * promote (fromDouble weightX3Y3)
143-
144-
!w = promote . fromDouble . (1 /) $
145-
weightX0Y0 + weightX1Y0 + weightX2Y0 + weightX3Y0
146-
+ weightX0Y1 + weightX1Y1 + weightX2Y1 + weightX3Y1
147-
+ weightX0Y2 + weightX1Y2 + weightX2Y2 + weightX3Y2
148-
+ weightX0Y3 + weightX1Y3 + weightX2Y3 + weightX3Y3
73+
interpolate (Bicubic a) border !sz getPx (i, j) =
74+
( f00 + f10 + f20 + f30
75+
+ f01 + f11 + f21 + f31
76+
+ f02 + f12 + f22 + f32
77+
+ f03 + f13 + f23 + f33 ) * promote (fromDouble (1 / w))
78+
where
79+
getPx' = handleBorderIndex border sz getPx
80+
{-# INLINE getPx' #-}
81+
distX x = fromIntegral x - i
82+
{-# INLINE distX #-}
83+
distY y = fromIntegral y - j
84+
{-# INLINE distY #-}
85+
weight x
86+
| x' <= 1 = ((a + 2) * x' - (a + 3)) * x2' + 1
87+
| x' < 2 = a * ((x2' - 5 * x' + 8) * x' - 4)
88+
| otherwise = 0
89+
where x' = abs x
90+
x2' = x' * x'
91+
{-# INLINE weight #-}
92+
!(i0, j0) = (i1 - 1, j1 - 1)
93+
!(i1, j1) = (floor i, floor j)
94+
!(i2, j2) = (i1 + 1, j1 + 1)
95+
!(i3, j3) = (i1 + 2, j1 + 2)
96+
97+
!weightX0 = weight (distX i0)
98+
!weightX1 = weight (distX i1)
99+
!weightX2 = weight (distX i2)
100+
!weightX3 = weight (distX i3)
101+
!weightY0 = weight (distY j0)
102+
!weightY1 = weight (distY j1)
103+
!weightY2 = weight (distY j2)
104+
!weightY3 = weight (distY j3)
105+
106+
!weightX0Y0 = weightX0 * weightY0
107+
!weightX1Y0 = weightX1 * weightY0
108+
!weightX2Y0 = weightX2 * weightY0
109+
!weightX3Y0 = weightX3 * weightY0
110+
111+
!weightX0Y1 = weightX0 * weightY1
112+
!weightX1Y1 = weightX1 * weightY1
113+
!weightX2Y1 = weightX2 * weightY1
114+
!weightX3Y1 = weightX3 * weightY1
115+
116+
!weightX0Y2 = weightX0 * weightY2
117+
!weightX1Y2 = weightX1 * weightY2
118+
!weightX2Y2 = weightX2 * weightY2
119+
!weightX3Y2 = weightX3 * weightY2
120+
121+
!weightX0Y3 = weightX0 * weightY3
122+
!weightX1Y3 = weightX1 * weightY3
123+
!weightX2Y3 = weightX2 * weightY3
124+
!weightX3Y3 = weightX3 * weightY3
125+
126+
!f00 = getPx' (i0, j0) * promote (fromDouble weightX0Y0)
127+
!f10 = getPx' (i1, j0) * promote (fromDouble weightX1Y0)
128+
!f20 = getPx' (i2, j0) * promote (fromDouble weightX2Y0)
129+
!f30 = getPx' (i3, j0) * promote (fromDouble weightX3Y0)
130+
131+
!f01 = getPx' (i0, j1) * promote (fromDouble weightX0Y1)
132+
!f11 = getPx' (i1, j1) * promote (fromDouble weightX1Y1)
133+
!f21 = getPx' (i2, j1) * promote (fromDouble weightX2Y1)
134+
!f31 = getPx' (i3, j1) * promote (fromDouble weightX3Y1)
135+
136+
!f02 = getPx' (i0, j2) * promote (fromDouble weightX0Y2)
137+
!f12 = getPx' (i1, j2) * promote (fromDouble weightX1Y2)
138+
!f22 = getPx' (i2, j2) * promote (fromDouble weightX2Y2)
139+
!f32 = getPx' (i3, j2) * promote (fromDouble weightX3Y2)
140+
141+
!f03 = getPx' (i0, j3) * promote (fromDouble weightX0Y3)
142+
!f13 = getPx' (i1, j3) * promote (fromDouble weightX1Y3)
143+
!f23 = getPx' (i2, j3) * promote (fromDouble weightX2Y3)
144+
!f33 = getPx' (i3, j3) * promote (fromDouble weightX3Y3)
145+
146+
!w = weightX0Y0 + weightX1Y0 + weightX2Y0 + weightX3Y0
147+
+ weightX0Y1 + weightX1Y1 + weightX2Y1 + weightX3Y1
148+
+ weightX0Y2 + weightX1Y2 + weightX2Y2 + weightX3Y2
149+
+ weightX0Y3 + weightX1Y3 + weightX2Y3 + weightX3Y3
149150
{-# INLINE interpolate #-}
150-

tests/Graphics/Image/ProcessingSpec.hs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ instance Arbitrary Interpol where
2626
case ix `mod` (3 :: Int) of
2727
0 -> return $ I1 Nearest
2828
1 -> return $ I2 Bilinear
29-
2 -> I3 . Bicubic <$> choose (-1, -0.5)
29+
2 -> I3 . Bicubic <$> pure (-1) -- choose (-1, -0.5)
3030
_ -> error $ "Unknown interpolation: " ++ show ix
3131

3232

@@ -74,25 +74,25 @@ prop_concatRotate img =
7474
rotate90 (leftToRight img $ rotate180 img)
7575

7676

77-
prop_rotate90 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Bool
78-
prop_rotate90 (I1 i) border img = rotate90 img == rotate i border (pi/2) img
79-
prop_rotate90 (I2 i) border img = rotate90 img == rotate i border (pi/2) img
80-
prop_rotate90 (I3 i) border img = rotate90 img == rotate i border (pi/2) img
77+
prop_rotate90 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Property
78+
prop_rotate90 (I1 i) border img = rotate90 img === rotate i border (pi/2) img
79+
prop_rotate90 (I2 i) border img = rotate90 img === rotate i border (pi/2) img
80+
prop_rotate90 (I3 i) border img = rotate90 img === rotate i border (pi/2) img
8181

82-
prop_rotate180 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Bool
83-
prop_rotate180 (I1 i) border img = rotate180 img == rotate i border pi img
84-
prop_rotate180 (I2 i) border img = rotate180 img == rotate i border pi img
85-
prop_rotate180 (I3 i) border img = rotate180 img == rotate i border pi img
82+
prop_rotate180 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Property
83+
prop_rotate180 (I1 i) border img = rotate180 img === rotate i border pi img
84+
prop_rotate180 (I2 i) border img = rotate180 img === rotate i border pi img
85+
prop_rotate180 (I3 i) border img = rotate180 img === rotate i border pi img
8686

87-
prop_rotate270 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Bool
88-
prop_rotate270 (I1 i) border img = rotate270 img == rotate i border (3*pi/2) img
89-
prop_rotate270 (I2 i) border img = rotate270 img == rotate i border (3*pi/2) img
90-
prop_rotate270 (I3 i) border img = rotate270 img == rotate i border (3*pi/2) img
87+
prop_rotate270 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Property
88+
prop_rotate270 (I1 i) border img = rotate270 img === rotate i border (3*pi/2) img
89+
prop_rotate270 (I2 i) border img = rotate270 img === rotate i border (3*pi/2) img
90+
prop_rotate270 (I3 i) border img = rotate270 img === rotate i border (3*pi/2) img
9191

92-
prop_rotate360 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Bool
93-
prop_rotate360 (I1 i) border img = (rotate270 . rotate90) img == rotate i border (2*pi) img
94-
prop_rotate360 (I2 i) border img = (rotate270 . rotate90) img == rotate i border (2*pi) img
95-
prop_rotate360 (I3 i) border img = (rotate270 . rotate90) img == rotate i border (2*pi) img
92+
prop_rotate360 :: Interpol -> Border (Pixel RGB Double) -> Image VU RGB Double -> Property
93+
prop_rotate360 (I1 i) border img = (rotate270 . rotate90) img === rotate i border (2*pi) img
94+
prop_rotate360 (I2 i) border img = (rotate270 . rotate90) img === rotate i border (2*pi) img
95+
prop_rotate360 (I3 i) border img = (rotate270 . rotate90) img === rotate i border (2*pi) img
9696

9797

9898
struct :: Image VS X Bit

0 commit comments

Comments
 (0)