{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
module Graphics.Image.Resample where
import qualified Codec.Picture as JPix
import qualified Codec.Picture.Types as JPix
import qualified Data.Vector.Storable as SArr
import Control.Monad
import Control.Monad.ST
import Data.STRef
scaleX2Bilinear :: JPix.Image JPix.PixelRGBA8 -> JPix.Image JPix.PixelRGBA8
scaleX2Bilinear img@(JPix.Image _ _ imgData) = runST $ do
buf@(JPix.MutableImage _ _ bufData) <- JPix.newMutableImage wScaled hScaled
let pbc = JPix.componentCount (undefined :: JPix.PixelRGBA8)
forM_ [0 .. hOrig-2] $ \j -> do
forM_ [0 .. wOrig-2] $ \k -> do
let linIndex = JPix.pixelBaseIndex img k j
orig₀₀ = JPix.unsafePixelAt imgData linIndex
orig₀₁ = JPix.unsafePixelAt imgData (linIndex+pbc)
orig₁₀ = JPix.unsafePixelAt imgData (linIndex+pbc*wOrig)
linIndexScaled = JPix.mutablePixelBaseIndex buf (k*2) (j*2)
JPix.unsafeWritePixel bufData linIndexScaled
$ orig₀₀
JPix.unsafeWritePixel bufData (linIndexScaled+pbc)
$ between orig₀₀ orig₀₁
JPix.unsafeWritePixel bufData (linIndexScaled+pbc*wScaled)
$ between orig₀₀ orig₁₀
JPix.unsafeWritePixel bufData (linIndexScaled+pbc+pbc*wScaled)
$ between orig₁₀ orig₀₁
forM_ [0 .. hOrig-2] $ \j -> do
forM_ [wOrig-1] $ \k -> do
let orig₀₀ = JPix.pixelAt img k j
orig₁₀ = JPix.pixelAt img k (j+1)
JPix.writePixel buf (k*2) (j*2) $ orig₀₀
JPix.writePixel buf (k*2) (j*2+1) $ between orig₀₀ orig₁₀
forM_ [hOrig-1] $ \j -> do
forM_ [0 .. wOrig-2] $ \k -> do
let orig₀₀ = JPix.pixelAt img k j
orig₀₁ = JPix.pixelAt img (k+1) j
JPix.writePixel buf (k*2) (j*2) $ orig₀₀
JPix.writePixel buf (k*2+1) (j*2) $ between orig₀₀ orig₀₁
forM_ [hOrig-1] $ \j -> do
forM_ [wOrig-1] $ \k -> do
let orig₀₀ = JPix.pixelAt img k j
JPix.writePixel buf (k*2) (j*2) $ orig₀₀
JPix.unsafeFreezeImage buf
where wOrig = JPix.imageWidth img
wScaled = 2 * wOrig - 1
hOrig = JPix.imageHeight img
hScaled = 2 * hOrig - 1
refiningScaleX2Bilinear ::
[(Int,Int)] -> ((Int,Int) -> JPix.PixelRGBA8)
-> JPix.Image JPix.PixelRGBA8 -> (JPix.Image JPix.PixelRGBA8, [(Int,Int)])
refiningScaleX2Bilinear hotSpots refineFn loRes = runST (do
intermediate <- JPix.unsafeThawImage $ scaleX2Bilinear loRes
alreadyDone <- JPix.unsafeThawImage
$ JPix.generateImage (\_ _ -> 0::JPix.Pixel8)
renderWidth renderHeight
alterations <- newSTRef []
let refineAt (ix,iy) = do
roughVal <- JPix.readPixel intermediate ix iy
let refinedVal = refineFn (ix,iy)
JPix.writePixel intermediate ix iy refinedVal
JPix.writePixel alreadyDone ix iy 1
notablyDifferent refinedVal roughVal ==> modifySTRef alterations ((ix,iy):)
refineBack (ix,iy) = do
doneBefore <- JPix.readPixel alreadyDone ix iy
doneBefore==0 ==> refineAt (ix,iy)
forM_ hotSpots $ \(irx,iry) -> do
irx > 0 ==> do
refineBack (2*irx - 1, 2*iry)
iry > 0 ==> refineBack (2*irx - 1, 2*iry - 1)
iry < loResHeight-1 ==> refineBack (2*irx - 1, 2*iry + 1)
irx < loResWidth-1 ==> do
refineAt (2*irx + 1, 2*iry)
iry > 0 ==> refineBack (2*irx + 1, 2*iry - 1)
iry < loResHeight-1 ==> refineAt (2*irx + 1, 2*iry + 1)
iry > 0 ==> refineBack (2*irx, 2*iry - 1)
iry < loResHeight-1 ==> refineAt (2*irx, 2*iry + 1)
alterationsDone <- readSTRef alterations
result <- JPix.unsafeFreezeImage intermediate
return (result, alterationsDone)
)
where loResWidth = JPix.imageWidth loRes
loResHeight = JPix.imageHeight loRes
renderWidth = loResWidth * 2 - 1
renderHeight = loResHeight * 2 - 1
infixr 1 ==>
(==>) = when
notablyDifferent :: JPix.PixelRGBA8 -> JPix.PixelRGBA8 -> Bool
notablyDifferent (JPix.PixelRGBA8 r₀ g₀ b₀ a₀) (JPix.PixelRGBA8 r₁ g₁ b₁ a₁)
= ( abs (fromIntegral r₀ - fromIntegral r₁)
+ abs (fromIntegral g₀ - fromIntegral g₁)
+ abs (fromIntegral b₀ - fromIntegral b₁)
+ abs (fromIntegral a₀ - fromIntegral a₁) :: Int )
> 16
between :: JPix.PixelRGBA8 -> JPix.PixelRGBA8 -> JPix.PixelRGBA8
between (JPix.PixelRGBA8 r₀ g₀ b₀ a₀) (JPix.PixelRGBA8 r₁ g₁ b₁ a₁)
= JPix.PixelRGBA8 (r₀`quot`2 + r₁`quot`2)
(g₀`quot`2 + g₁`quot`2)
(b₀`quot`2 + b₁`quot`2)
(a₀`quot`2 + a₁`quot`2)