diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -11,6 +11,7 @@
                          , argContrast :: Double
                          , argGamma :: Int
                          , argBrightness :: Double
+                         , argCompress :: Int
                          }
 
   opts = Options { file = ""
@@ -22,6 +23,7 @@
                  , argContrast = 0
                  , argGamma = 1
                  , argBrightness = 0
+                 , argCompress = 0
                  }
 
   main :: IO ()
@@ -39,6 +41,7 @@
         putStrLn "  --rotate <n> - rotate image by n degrees"
         putStrLn "  --grayscale - turn the image grayscale"
         putStrLn "  --invert - invert (negative) the image"
+        putStrLn "  --compress <n> - approximate the (width - n)-th rank of image using SVD, note: this is not size compression, a number between 0 (no compression) and image width (full compression)"
         putStrLn "  --output <filename> - output name, defaults to output.png"
       else do 
         let options = parseArgs args opts
@@ -49,13 +52,14 @@
           Left err -> print err
           Right p -> do
             let edited = rotate (argRotate options) Nothing 
-                      . fade (argFade options / 100)
-                      . contrast (argContrast options)
-                      . gamma (argGamma options)
-                      . brightness (argBrightness options)
-                      . conditionalFn grayscale (argGrayscale options) 
-                      . conditionalFn invert (argInvert options) $ p
-            writePicturePng "output.png" edited
+                       . fade (argFade options / 100)
+                       . contrast (argContrast options)
+                       . gamma (argGamma options)
+                       . brightness (argBrightness options)
+                       . conditionalFn grayscale (argGrayscale options) 
+                       . conditionalFn invert (argInvert options)
+                       . compress (argCompress options) $ p
+            writePicturePng (output options) edited
             
         return ()
 
@@ -72,6 +76,7 @@
   parseArgs ("--contrast":n:rest) opts = parseArgs rest (opts { argContrast = read n })
   parseArgs ("--brightness":n:rest) opts = parseArgs rest (opts { argBrightness = read n })
   parseArgs ("--gamma":n:rest) opts = parseArgs rest (opts { argGamma = read n })
+  parseArgs ("--compress":n:rest) opts = parseArgs rest (opts { argCompress = read n })
   parseArgs ("--output":n:rest) opts = parseArgs rest (opts { output = n })
   parseArgs (name:rest) opts = parseArgs rest (opts { file = name })
 
diff --git a/picedit.cabal b/picedit.cabal
--- a/picedit.cabal
+++ b/picedit.cabal
@@ -1,5 +1,5 @@
 name:                picedit
-version:             0.1.0.0
+version:             0.1.1.0
 synopsis:            simple image manipulation functions
 description:         Simple set of functions for image manipulation: contrast, brightnesss, rotation, etc.
 homepage:            https://github.com/mdibaiee/picedit#readme
diff --git a/src/Data/Picture.hs b/src/Data/Picture.hs
--- a/src/Data/Picture.hs
+++ b/src/Data/Picture.hs
@@ -3,25 +3,30 @@
 {-# LANGUAGE TypeFamilies #-}
 
 {-|
-Module      : Picture
-Description : manipulation functions
+Module      : Data.Picture
+Description : picture manipulation functions
 Copyright   : (c) Mahdi Dibaiee, 2016
 License     : GPL-3
 Maintainer  : mdibaiee@aol.com
 Stability   : experimental
 Portability : POSIX
 -}
-module Data.Picture ( grayscale
-                    , readPicture
-                    , fromImage
-                    , toImage
-                    , writePicturePng
+module Data.Picture ( Picture
+                    -- * Manipulation functions
+                    , grayscale
                     , fade
                     , rotate
                     , contrast
                     , brightness
                     , gamma
                     , invert
+                    , compress
+                    -- * Converting between Image and Picture
+                    , fromImage
+                    , toImage
+                    -- * IO operations
+                    , readPicture
+                    , writePicturePng
                     )
   where
 
@@ -30,11 +35,12 @@
     import qualified Data.Vector.Storable as V
     import System.IO
     import Data.Maybe
+    import Debug.Trace
 
-    -- | 'Picture' type is just a triple of color channel matrices: (R, G, B)
+    -- | (R, G, B) color channels
     type Picture = (Matrix Double, Matrix Double, Matrix Double)
 
-    -- |Converts a JuicyPixel 'Image PixelRGB8' to 'Picture'
+    -- | Converts a JuicyPixel 'Image PixelRGB8' to 'Picture'
     fromImage :: Image PixelRGB8 -> Picture
     fromImage Image { imageWidth = w, imageHeight = h, imageData = vec } =
      let [r, g, b] = map (reshape w . V.fromList . reverse) (snd $ V.foldl' gp (0, [[],[],[]]) (V.map fromIntegral vec))
@@ -46,7 +52,7 @@
            (1, [r, g, b]) -> (2, [r, x:g, b])
            (2, [r, g, b]) -> (0, [r, g, x:b])
 
-    -- |Converts a 'Picture' to JuicyPixel 'Image PixelRGB8'
+    -- | Converts a 'Picture' to JuicyPixel 'Image PixelRGB8'
     toImage :: Picture -> Image PixelRGB8
     toImage (r, g, b) = 
       let (fr, fg, fb) = (toList $ flatten r, toList $ flatten g, toList $ flatten b)
@@ -104,9 +110,8 @@
       where
         f = cmap (`subtract` 255)
 
-    {- | Rotate 'Picture' for the specified degrees, around the specified origin.
-     - If the origin is `Nothing`, rotates around the center
-     -}
+    -- | Rotate 'Picture' for the specified degrees, around the specified origin.
+    -- If the origin is `Nothing`, rotates around the center
     rotate :: Double -> Maybe (Int, Int) -> Picture -> Picture
     rotate deg orig (r, g, b) = (f r, f g, f b)
       where
@@ -130,6 +135,18 @@
         movedIndices = map (\[x, y] -> [x + originX, y + originY]) rotatedIndices
 
         f m = reshape (cols m) $ fromList $ map (\[x, y] -> if y < 0 || y >= rows r || x < 0 || x >= cols r then 255 else m `atIndex` (y, x)) movedIndices
+
+    -- | Compress the image using SVD
+    -- note: this is not size compression, it's just a k-rank approximation of the image
+    compress :: Int -> Picture -> Picture
+    compress rate (r, g, b) = (f r, f g, f b)
+      where
+        k = cols r - rate
+        f m =
+          let (u, s, v) = svd m
+              si = diagRect 0 s (rows m) (cols m)
+              (mu, ms, mv) = (u ?? (All, Take k), si ?? (Take k, Take k), (tr v) ?? (Take k, All))
+          in mu <> ms <> mv
 
     bound (l, u) x = max l $ min u x
     pixelBound = bound (0, 255)
