module Graphics.Rasterific.BiSampleable
( BiSampleable( .. )
, bilinearInterpolation
) where
import Codec.Picture( PixelRGBA8( .. ) )
import Graphics.Rasterific.Linear
import Graphics.Rasterific.Types
import Graphics.Rasterific.Compositor
import Graphics.Rasterific.Shading
import Graphics.Rasterific.PatchTypes
import Graphics.Rasterific.Transformations
import Codec.Picture( Pixel( .. ) )
class BiSampleable sampled px | sampled -> px where
interpolate :: sampled -> Float -> Float -> px
instance (Pixel px, Modulable (PixelBaseComponent px))
=> BiSampleable (ParametricValues px) px where
interpolate = bilinearPixelInterpolation
instance ( InterpolablePixel px
, Num (Holder px Float)
) => BiSampleable (CubicCoefficient px) px where
interpolate = bicubicInterpolation
instance BiSampleable (ImageMesh PixelRGBA8) PixelRGBA8 where
interpolate imesh xb yb = sampledImageShader (_meshImage imesh) SamplerPad x y
where (V2 x y) = applyTransformation (_meshTransform imesh) (V2 xb yb)
bilinearPixelInterpolation :: (Pixel px, Modulable (PixelBaseComponent px))
=> ParametricValues px -> Float -> Float -> px
bilinearPixelInterpolation (ParametricValues { .. }) !dx !dy =
mixWith (const $ alphaOver covY icovY)
(mixWith (const $ alphaOver covX icovX) _northValue _eastValue)
(mixWith (const $ alphaOver covX icovX) _westValue _southValue)
where
(!covX, !icovX) = clampCoverage dx
(!covY, !icovY) = clampCoverage dy
bilinearInterpolation :: InterpolablePixel px
=> ParametricValues px -> Float -> Float -> px
bilinearInterpolation ParametricValues { .. } u v = fromFloatPixel $ lerp v uBottom uTop where
!uTop = lerp u (toFloatPixel _eastValue) (toFloatPixel _northValue)
!uBottom = lerp u (toFloatPixel _southValue) (toFloatPixel _westValue)
bicubicInterpolation :: forall px . (InterpolablePixel px, Num (Holder px Float))
=> CubicCoefficient px -> Float -> Float -> px
bicubicInterpolation params x y =
fromFloatPixel . fmap clamp $ af ^+^ bf ^+^ cf ^+^ df
where
ParametricValues a b c d = getCubicCoefficients params
maxi = maxRepresentable (Proxy :: Proxy px)
clamp = max 0 . min maxi
xv, vy, vyy, vyyy :: V4 Float
xv = V4 1 x (x*x) (x*x*x)
vy = xv ^* y
vyy = vy ^* y
vyyy = vyy ^* y
v1 ^^*^ v2 = (^*) <$> v1 <*> v2
V4 af bf cf df = (a ^^*^ xv) ^+^ (b ^^*^ vy) ^+^ (c ^^*^ vyy) ^+^ (d ^^*^ vyyy)