diff --git a/Codec/Picture/Repa.hs b/Codec/Picture/Repa.hs
--- a/Codec/Picture/Repa.hs
+++ b/Codec/Picture/Repa.hs
@@ -1,8 +1,8 @@
-{-# LANGUAGE EmptyDataDecls, FlexibleInstances, TypeSynonymInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE EmptyDataDecls, FlexibleInstances, TypeSynonymInstances, MultiParamTypeClasses, ViewPatterns #-}
 module Codec.Picture.Repa
        ( -- * Primitive types and operations
          Img, imgData
-       , convertImage
+       , convertImage, imgToImage
        -- * Generic interface
        , readImage, decodeImage
        -- * Monomorphic image decoding functions
@@ -16,6 +16,8 @@
        , reverseColorChannel
        , flipHorizontally, flipVertically
        , vConcat, hConcat
+       -- * Saving Images
+       , module Codec.Picture.Saving
        -- * Internal Functionallity (exported for advanced uses)
        , ToRGBAChannels(..)
        ) where
@@ -27,6 +29,7 @@
 import qualified Codec.Picture as P
 import Codec.Picture hiding (readImage, decodeImage)
 import Codec.Picture.Types hiding (convertImage)
+import Codec.Picture.Saving
 import qualified Data.Vector.Storable as S
 import Foreign.ForeignPtr
 import Data.Word
@@ -64,7 +67,7 @@
 -- |@toByteString arr@ converts images to bytestrings, which is often useful
 -- for Gloss.
 toByteString :: Img a -> B.ByteString
-toByteString (Img arr) =
+toByteString ((onImg flipVertically . reverseColorChannel) -> Img arr) =
   let fp = RF.toForeignPtr arr
       (Z :. row :. col :. chan) = extent arr
   in BI.fromForeignPtr fp 0 (col * row * chan)
@@ -200,7 +203,7 @@
 
 instance ToRGBAChannels PixelYA8 where
   toRGBAChannels = promotePixel
-  
+
 instance ToRGBAChannels Pixel8 where
   toRGBAChannels = promotePixel
 
@@ -228,28 +231,28 @@
   convertImage (ImageRGB8 i) = convertImage i
   convertImage (ImageRGBA8 i) = convertImage i -- zeroCopyConvert 4 i
   convertImage (ImageYCbCr8 i) = convertImage i
-  
+
 instance ConvertImage DynamicImage RGB where
   convertImage (ImageY8 i) = convertImage i
   convertImage (ImageYA8 i) = convertImage i
   convertImage (ImageRGB8 i) = convertImage i -- zeroCopyConvert 3 i
   convertImage (ImageRGBA8 i) = convertImage i
   convertImage (ImageYCbCr8 i) = convertImage i
-  
+
 instance ConvertImage DynamicImage R where
   convertImage (ImageY8 i) = convertImage i
   convertImage (ImageYA8 i) = convertImage i
   convertImage (ImageRGB8 i) = convertImage i
   convertImage (ImageRGBA8 i) = convertImage i
   convertImage (ImageYCbCr8 i) = convertImage i
-  
+
 instance ConvertImage DynamicImage G where
   convertImage (ImageY8 i) = convertImage i
   convertImage (ImageYA8 i) = convertImage i
   convertImage (ImageRGB8 i) = convertImage i
   convertImage (ImageRGBA8 i) = convertImage i
   convertImage (ImageYCbCr8 i) = convertImage i
-  
+
 instance ConvertImage DynamicImage B where
   convertImage (ImageY8 i) = convertImage i
   convertImage (ImageYA8 i) = convertImage i
@@ -260,39 +263,54 @@
 instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) RGBA where
   convertImage p@(Image w h dat) =
     let z = 4
-    in Img $ R.computeS $ R.fromFunction (Z :. h :. w :. z) 
-                                    (\(Z :. y :. x :. z') -> getPixel x y (z - z' - 1) p)
-  
+    in Img $ R.computeS $ R.fromFunction (Z :. h :. w :. z)
+                                    (\(Z :. y :. x :. z') -> getPixel x y z' p)
+
 instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) RGB where
   convertImage p@(Image w h dat) =
     let z = 3
     in Img $ R.computeS $ R.fromFunction (Z :. h :. w :. z)
-                            (\(Z :. y :. x :. z') -> getPixel x y (z' - z -1) p)
+                            (\(Z :. y :. x :. z') -> getPixel x y z' p)
 
 instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) R where
   convertImage p@(Image w h dat) =
     let z = 1
     in Img $ R.computeS $ R.fromFunction (Z :. h :. w :. z)
                             (\(Z :. y :. x :. z) -> getPixel x y 0 p)
-       
+
 instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) G where
   convertImage p@(Image w h dat) =
     let z = 1
     in Img $ R.computeS $ R.fromFunction (Z :. h :. w :. z)
                             (\(Z :. y :. x :. z) -> getPixel x y 1 p)
-       
+
 instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) B where
   convertImage p@(Image w h dat) =
     let z = 1
     in Img $ R.computeS $ R.fromFunction (Z :. h :. w :. z)
                             (\(Z :. y :. x :. z) -> getPixel x y 2 p)
 
+-- Convert a repa-based 'Img' to a JuicyPixels Vector-based 'DynaimcImage'.
+imgToImage :: Img a -> DynamicImage
+imgToImage (Img arr) =
+        let e@(Z :. row :. col :. z)  = extent arr
+            f co ro =
+               let r = R.unsafeIndex arr (Z:.ro:.co:.(max 0 0))
+                   g = R.unsafeIndex arr (Z:.ro:.co:.(max 0 1))
+                   b = R.unsafeIndex arr (Z:.ro:.co:.(max 0 2))
+                   a = if z == 4 then R.unsafeIndex arr (Z:.ro:.co:.3)
+                                 else 255
+               in PixelRGBA8 r g b a
+        in ImageRGBA8 (generateImage f col row)
+
+-- |Flip an image vertically
 flipVertically :: Array F DIM3 Word8 -> Array F DIM3 Word8
 flipVertically rp = (R.computeS $ backpermute e order rp)
  where
  e@(Z :. row :. col :. z) = extent rp
  order (Z :. oldRow :. oldCol :. oldChan) = Z :. row - oldRow - 1 :. oldCol :. oldChan
 
+-- |Flip an image horizontally
 flipHorizontally :: Array F DIM3 Word8 -> Array F DIM3 Word8
 flipHorizontally rp = (R.computeS $ backpermute e order rp)
  where
@@ -311,13 +329,17 @@
         | h < hb    = fb (Z :. h :. w :. d)
         | otherwise = fa (Z :. h - hb :. w :. d)
 
-vConcat :: [Array F DIM3 Word8] -> Array F DIM3 Word8
+-- |Combines a list of images such that the first image is on top, then
+-- the second, and so on.
+vConcat :: [Img a] -> Img a
 vConcat [] = error "vConcat: Can not concat an empty list into a Repa array"
-vConcat xs = R.computeS $ Prelude.foldl1 vStack (Prelude.map R.delay xs)
+vConcat xs = Img $ R.computeS $ Prelude.foldl1 vStack (Prelude.map (R.delay . imgData) xs)
 
-hConcat :: [Array F DIM3 Word8] -> Array F DIM3 Word8
+-- |Combines a list of images such that the first image is on the left, then
+-- the second, and so on.
+hConcat :: [Img a] -> Img a
 hConcat [] = error "hConcat: Can not concat an empty list into a Repa array"
-hConcat xs = R.computeS $ Prelude.foldl1 hStack (Prelude.map R.delay xs)
+hConcat xs = Img $ R.computeS $ Prelude.foldl1 hStack (Prelude.map (R.delay . imgData) xs)
 
 -- |Stack the images horozontally, placing the first image on the left of the second.
 hStack :: Array R.D DIM3 Word8 -> Array R.D DIM3 Word8 -> Array R.D DIM3 Word8
@@ -330,8 +352,12 @@
         | c < ca    = fa (Z :. r :. c :. d)
         | otherwise = fb (Z :. r :. c - ca :. d)
 
+-- | A histogram is a one dimensional array where each element
+-- indicates how many pixels held the value represented by the element's
+-- index.
 type Histogram = R.Array R.D R.DIM1 Word8
 
+-- | Compute the RGBA historgrams of the image.
 histograms :: Img a -> (Histogram, Histogram, Histogram, Histogram)
 histograms (Img arr) =
     let (Z:.nrRow:.nrCol:._) = R.extent arr
@@ -345,3 +371,9 @@
              in (incElem r hR, incElem g hG, incElem b hB, incElem a hA))
           (zero,zero,zero,zero)
           [ (row,col) | row <- [0..nrRow-1], col <- [0..nrCol-1] ]
+
+-- | Threshold takes an image and a color channel and a level, returning an
+-- image with each pixel of that color channel zeroed or saturated
+-- depending on if it was @<=@ the bound or not (@>@).
+-- threshhold :: Img a -> Int -> Word8 -> Img a
+-- threshhold (Img arr) chan level = do
diff --git a/JuicyPixels-repa.cabal b/JuicyPixels-repa.cabal
--- a/JuicyPixels-repa.cabal
+++ b/JuicyPixels-repa.cabal
@@ -1,5 +1,5 @@
 Name:                JuicyPixels-repa
-Version:             0.6.2
+Version:             0.7
 Synopsis:            Convenience functions to obtain array representations of images.
 Description:         This wraps the Juicy.Pixels library to convert into 'Repa' and 
                      'Data.Vector.Storable' formats.
