diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # avif
 
+# 0.1.0.2
+
+  * Use finalizers under the hood
+
 ## 0.1.0.1
 
   * Bundle test daa
diff --git a/avif.cabal b/avif.cabal
--- a/avif.cabal
+++ b/avif.cabal
@@ -1,6 +1,6 @@
 cabal-version:   1.18
 name:            avif
-version:         0.1.0.1
+version:         0.1.0.2
 license:         AGPL-3
 license-file:    LICENSE
 copyright:       Copyright: (c) 2021 Vanessa McHale
@@ -25,7 +25,7 @@
     hs-source-dirs:   src
     default-language: Haskell2010
     ghc-options:      -Wall
-    build-depends:    base >=4.7 && <5
+    build-depends:    base >=4.8 && <5
                     , bytestring
                     , JuicyPixels
                     , vector
@@ -52,8 +52,6 @@
     hs-source-dirs:   test
     default-language: Haskell2010
     ghc-options:      -threaded -rtsopts "-with-rtsopts=-N -K1K" -Wall
-    -- libyuv is wrong?? lol
-    -- extra-libraries:  jpeg
     build-depends:
         base,
         avif,
diff --git a/src/Codec/Avif.chs b/src/Codec/Avif.chs
--- a/src/Codec/Avif.chs
+++ b/src/Codec/Avif.chs
@@ -3,13 +3,11 @@
                   ) where
 
 import Codec.Avif.FFI
-import Codec.Picture (Image (Image), PixelRGBA8, PixelYCbCr8)
-import Control.Applicative (pure)
+import Codec.Picture (Image (Image), PixelRGBA8)
 import Control.Exception (throwIO)
 import qualified Data.ByteString as BS
 import Data.ByteString.Internal (memcpy)
 import qualified Data.ByteString.Unsafe as BS
-import Data.Functor ((<$>), (<$))
 import Foreign.Ptr (castPtr)
 import Foreign.ForeignPtr (castForeignPtr, newForeignPtr, mallocForeignPtrBytes, withForeignPtr)
 import Foreign.Marshal (allocaBytes)
@@ -18,8 +16,6 @@
 
 #include <avif/avif.h>
 
--- PixelYCbCr8?
-
 throwRes :: AvifResult -> IO ()
 throwRes AvifResultOk = pure (); throwRes err = throwIO err
 
@@ -27,9 +23,10 @@
 encode :: Image PixelRGBA8 -> BS.ByteString
 encode img = unsafePerformIO $ do
     avifImgPtr <- avifImageCreate (fromIntegral w) (fromIntegral h) 8 AvifPixelFormatYuv444
+    avifImg <- castForeignPtr <$> newForeignPtr avifImageDestroy (castPtr avifImgPtr)
     res <- allocaBytes {# sizeof avifRGBImage #} $ \rgbImagePtr ->
         allocaBytes {# sizeof avifRWData #} $ \rwDataPtr -> do
-            avifRGBImageSetDefaults rgbImagePtr avifImgPtr
+            avifRGBImageSetDefaults rgbImagePtr avifImg
             pxSz <- avifRGBImagePixelSize rgbImagePtr
 
             preEnc <- avifEncoderCreate
@@ -37,21 +34,19 @@
 
             withForeignPtr imgPtr $ \iPtr -> do
 
-                {# set avifRGBImage.height #} rgbImagePtr (fromIntegral h)
-                {# set avifRGBImage.width #} rgbImagePtr (fromIntegral w)
                 {# set avifRGBImage.pixels #} rgbImagePtr (castPtr iPtr)
                 {# set avifRGBImage.rowBytes #} rgbImagePtr (fromIntegral w*pxSz)
 
-                throwRes =<< avifImageRGBToYUV avifImgPtr rgbImagePtr
+                throwRes =<< avifImageRGBToYUV avifImg rgbImagePtr
 
-                throwRes =<< avifEncoderWrite enc avifImgPtr rwDataPtr
+                throwRes =<< avifEncoderWrite enc avifImg rwDataPtr
 
                 sz <- {# get avifRWData->size #} rwDataPtr
                 bs <- {# get avifRWData->data #} rwDataPtr
 
                 BS.packCStringLen (castPtr bs, fromIntegral sz)
 
-    res <$ avifImageDestroy avifImgPtr
+    pure res
 
     where (Image w h bytes) = img
           (imgPtr, _) = VS.unsafeToForeignPtr0 bytes
@@ -61,8 +56,10 @@
 decode bs = unsafePerformIO $ BS.unsafeUseAsCStringLen bs $ \(ptr, sz) -> do
     preDec <- avifDecoderCreate
     dec <- castForeignPtr <$> newForeignPtr avifDecoderDestroy (castPtr preDec)
-    avifImg <- avifImageCreateEmpty
 
+    avifImgPtr <- avifImageCreateEmpty
+    avifImg <- castForeignPtr <$> newForeignPtr avifImageDestroy (castPtr avifImgPtr)
+
     throwRes =<< avifDecoderReadMemory dec avifImg (castPtr ptr) (fromIntegral sz)
 
     allocaBytes {# sizeof avifRGBImage #} $ \rgbImagePtr -> do
@@ -76,10 +73,10 @@
 
         pxPtr <- {# get avifRGBImage->pixels #} rgbImagePtr
 
-        let sz' = w * h * pxSz
+        let sz' = w*h*pxSz
 
         outBytes <- mallocForeignPtrBytes (fromIntegral sz')
 
         withForeignPtr outBytes $ \outPtr -> do
             memcpy (castPtr outPtr) (castPtr pxPtr) (fromIntegral sz')
-            Image (fromIntegral w) (fromIntegral h) (VS.unsafeFromForeignPtr0 outBytes (fromIntegral sz')) <$ (avifRGBImageFreePixels rgbImagePtr *> avifImageDestroy avifImg)
+            Image (fromIntegral w) (fromIntegral h) (VS.unsafeFromForeignPtr0 outBytes (fromIntegral sz')) <$ (avifRGBImageFreePixels rgbImagePtr)
diff --git a/src/Codec/Avif/FFI.chs b/src/Codec/Avif/FFI.chs
--- a/src/Codec/Avif/FFI.chs
+++ b/src/Codec/Avif/FFI.chs
@@ -21,7 +21,7 @@
 
 import Control.Exception (Exception)
 import Data.Coerce (coerce)
-import Data.Typeable (Typeable (..))
+import Data.Typeable (Typeable)
 import Foreign.C.Types (CInt, CSize)
 import Foreign.Ptr (castPtr, Ptr)
 
@@ -35,8 +35,9 @@
 
 instance Exception AvifResult where
 
--- {# pointer *LZ_Decoder as LZDecoderPtr foreign finalizer LZ_decompress_close as ^ -> LZDecoder #}
-data AvifImage -- TODO: finalizer for AvifImage
+{# pointer *avifImage as AvifImagePtr foreign finalizer avifImageDestroy as ^ -> AvifImage #}
+
+data AvifImage
 data AvifEncoder
 data AvifDecoder
 data AvifRwData
@@ -45,21 +46,20 @@
 {# pointer *avifEncoder as AvifEncoderPtr foreign finalizer avifEncoderDestroy as ^ -> AvifEncoder #}
 {# pointer *avifDecoder as AvifDecoderPtr foreign finalizer avifDecoderDestroy as ^ -> AvifDecoder #}
 
-{# fun avifImageCreate as ^ { `CInt', `CInt', `CInt', `AvifPixelFormat' } -> `Ptr AvifImage' castPtr #}
-{# fun avifImageCreateEmpty as ^ { } -> `Ptr AvifImage' castPtr #}
-{# fun avifImageDestroy as ^ { castPtr `Ptr AvifImage' } -> `()' #}
+{# fun avifImageCreate as ^ { `CInt', `CInt', `CInt', `AvifPixelFormat' } -> `Ptr AvifImage' id #}
+{# fun avifImageCreateEmpty as ^ { } -> `Ptr AvifImage' id #}
 
 {# fun avifEncoderCreate as ^ { } -> `Ptr AvifEncoder' castPtr #}
-{# fun avifEncoderWrite as ^ { `AvifEncoderPtr', castPtr `Ptr AvifImage', castPtr `Ptr AvifRwData' } -> `AvifResult' #}
+{# fun avifEncoderWrite as ^ { `AvifEncoderPtr', `AvifImagePtr', castPtr `Ptr AvifRwData' } -> `AvifResult' #}
 
 {# fun avifDecoderCreate as ^ { } -> `Ptr AvifDecoder' castPtr #}
-{# fun avifDecoderReadMemory as ^ { `AvifDecoderPtr', castPtr `Ptr AvifImage', castPtr `Ptr UInt8', coerce `CSize' } -> `AvifResult' #}
+{# fun avifDecoderReadMemory as ^ { `AvifDecoderPtr', `AvifImagePtr', castPtr `Ptr UInt8', coerce `CSize' } -> `AvifResult' #}
 
-{# fun avifRGBImageSetDefaults as ^ { castPtr `Ptr AvifRGBImage', castPtr `Ptr AvifImage' } -> `()' #}
+{# fun avifRGBImageSetDefaults as ^ { castPtr `Ptr AvifRGBImage', `AvifImagePtr' } -> `()' #}
 {# fun avifRGBImagePixelSize as ^ { castPtr `Ptr AvifRGBImage' } -> `UInt32' id #}
 
-{# fun avifImageRGBToYUV as ^ { castPtr `Ptr AvifImage', castPtr `Ptr AvifRGBImage' } -> `AvifResult' #}
-{# fun avifImageYUVToRGB as ^ { castPtr `Ptr AvifImage', castPtr `Ptr AvifRGBImage' } -> `AvifResult' #}
+{# fun avifImageRGBToYUV as ^ { `AvifImagePtr', castPtr `Ptr AvifRGBImage' } -> `AvifResult' #}
+{# fun avifImageYUVToRGB as ^ { `AvifImagePtr', castPtr `Ptr AvifRGBImage' } -> `AvifResult' #}
 
 {# fun avifRGBImageAllocatePixels as ^ { castPtr `Ptr AvifRGBImage' } -> `()' #}
 {# fun avifRGBImageFreePixels as ^ { castPtr `Ptr AvifRGBImage' } -> `()' #}
