diff --git a/.hg_archival.txt b/.hg_archival.txt
new file mode 100644
--- /dev/null
+++ b/.hg_archival.txt
@@ -0,0 +1,5 @@
+repo: 6a8148a175dcc23043059d4229a0e1ae3745688f
+node: e993863c51c531869ca224a56d6657c494088af5
+branch: default
+latesttag: null
+latesttagdistance: 2
diff --git a/.hgignore b/.hgignore
new file mode 100644
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,12 @@
+syntax: glob
+\#*\#
+.\#*
+*~
+*.bak
+*.log
+*.orig
+*.rej
+core
+core.*
+dist/*
+
diff --git a/COPYING b/COPYING
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,25 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/isiz.cabal b/isiz.cabal
new file mode 100644
--- /dev/null
+++ b/isiz.cabal
@@ -0,0 +1,19 @@
+Name:           isiz
+Version:        0.0.1
+Synopsis:       A program to show the size of image and whether suitable for wallpaper.
+License:        BSD3
+License-file:   COPYING
+Author:         Hironao Komatsu
+Maintainer:     Hironao Komatsu <hirkmt@gmail.com>
+Build-Type:     Simple
+Cabal-Version:  >= 1.8
+Stability:      alpha
+Category:       Graphics
+Tested-With:    GHC == 7.6.3
+
+Extra-Source-Files: COPYING
+
+Executable      isiz
+    build-depends:  base >= 4 && < 5, gtk3
+    Main-is:        isiz.hs
+    Hs-Source-Dirs: src
diff --git a/src/PixbufExtras.hs b/src/PixbufExtras.hs
new file mode 100644
--- /dev/null
+++ b/src/PixbufExtras.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# OPTIONS -Wall -O #-}
+
+module PixbufExtras (pixbufGetSizeInfoFile) where
+
+import Control.Applicative (Applicative, liftA, pure)
+import Data.Word
+import Foreign.C
+import Foreign.Marshal.Alloc
+import Foreign.Ptr
+import Foreign.Storable
+import Graphics.UI.Gtk.Gdk.Pixbuf ()
+
+-- | Read file metadata and return image size
+pixbufGetSizeInfoFile :: FilePath -> IO (Maybe (Int, Int))
+pixbufGetSizeInfoFile fp =
+    withCString fp $ \cfp ->
+        alloca $ \wp -> alloca $ \hp -> pixbufGetFileInfo cfp wp hp
+                        >>= ptrMaybeA (\_ -> peek wp >>= \w
+                                          -> peek hp >>= \h
+                                          -> return (w, h))
+
+-- FIXME: the return value shall not be a Ptr to a Word.
+foreign import ccall "static gdk/gdkpixbuf.h gdk_pixbuf_get_file_info"
+    pixbufGetFileInfo :: CString -> Ptr Int -> Ptr Int -> IO (Ptr Word)
+
+-- | Apply function if the pointer is not NULL
+ptrMaybeA :: Applicative m => (Ptr a -> m b) -> Ptr a -> m (Maybe b)
+ptrMaybeA f p | p == nullPtr = pure  Nothing
+              | otherwise    = liftA Just $ f p
diff --git a/src/isiz.hs b/src/isiz.hs
new file mode 100644
--- /dev/null
+++ b/src/isiz.hs
@@ -0,0 +1,181 @@
+{-# OPTIONS -O -Wall #-}
+
+import Control.Applicative ((<$>), (<*>), (<|>))
+import Control.Monad (foldM, join)
+import Data.List (find)
+import Data.Maybe (catMaybes)
+import System.Console.GetOpt
+import System.Environment (getArgs)
+import System.Exit (ExitCode (..), exitSuccess, exitWith)
+import Text.Printf
+import PixbufExtras
+
+data RunMode = RunModeDefault
+             | RunModeList Bool
+             | RunModeSilent Bool
+               deriving (Eq, Show)
+
+data ImageSize = ZeroSized
+               | Ratio4_3
+               | Ratio5_4
+               | Ratio16_9
+               | Ratio16_10
+               | Ratio21_9
+               | NonStdHVGA
+               | NonStdWVGA
+               | NonStdWVGAPlus
+               | NonStdFWVGA
+               | NonStdWSVGA
+               | NonStdWXGA
+               | NonStdUnnamed
+               | NonStdWSXGA
+               | OtherSize
+                 deriving (Eq, Show)
+
+sizeName :: ImageSize -> String
+sizeName ZeroSized      = "(zero-sized)"
+sizeName Ratio4_3       = "4:3"
+sizeName Ratio5_4       = "5:4"
+sizeName Ratio16_9      = "16:9"
+sizeName Ratio16_10     = "16:10"
+sizeName Ratio21_9      = "21:9"
+sizeName NonStdHVGA     = "HVGA"
+sizeName NonStdWVGA     = "WVGA"
+sizeName NonStdWVGAPlus = "WVGA+"
+sizeName NonStdFWVGA    = "FWVGA"
+sizeName NonStdWSVGA    = "WSVGA"
+sizeName NonStdWXGA     = "WXGA"
+sizeName NonStdUnnamed  = "(unnamed)"
+sizeName NonStdWSXGA    = "WSXGA"
+sizeName OtherSize      = "(other)"
+
+nonStdSizes :: [(Int, Int, ImageSize)]
+nonStdSizes = [ ( 480, 320, NonStdHVGA    )
+              , ( 800, 480, NonStdWVGA    )
+              , ( 854, 480, NonStdWVGAPlus)
+              , ( 864, 480, NonStdFWVGA   )
+              , (1024, 600, NonStdWSVGA   )
+              , (1280, 768, NonStdWXGA    )
+              , (1366, 768, NonStdUnnamed )
+              , (1280, 854, NonStdWSXGA   ) ]
+
+isWallpaper :: ImageSize -> Bool
+isWallpaper ZeroSized      = False
+isWallpaper OtherSize      = False
+isWallpaper _              = True
+
+checkSize :: Int -> Int -> Maybe ImageSize
+checkSize w h
+    | w <  h    = checkSize h w
+    | h <  0    = Nothing
+    | h == 0    = Just ZeroSized
+    | otherwise =
+        let ratio       = fromIntegral h / fromIntegral w
+            minDelta    = 1e-2 :: Double
+            testD s     = abs (ratio - s) < minDelta
+            trd (_,_,c) = c
+        in case () of
+             _ | testD (3/ 4) -> Just Ratio4_3
+             _ | testD (4/ 5) -> Just Ratio5_4
+             _ | testD (9/16) -> Just Ratio16_9
+             _ | testD (5/ 8) -> Just Ratio16_10
+             _ | testD (3/ 7) -> Just Ratio21_9
+             _                ->
+                 (trd <$>
+                  find (\(u, v, _) -> u == w && v == h)
+                       nonStdSizes) <|> Just OtherSize
+
+-- | read from file and return its size and whether suitable for wallpaper
+checkFile :: FilePath -> IO (Maybe (ImageSize, Bool, Int, Int))
+checkFile path = do
+  mg <- pixbufGetSizeInfoFile path
+  let ms = join $ uncurry checkSize <$> mg
+      mp = isWallpaper <$> ms
+  return $ (\(w, h) s p -> (s, p, w, h)) <$> mg <*> ms <*> mp
+
+-- | flipped <$>
+(<$$>) :: Functor m => m a -> (a -> b) -> m b
+(<$$>) = flip fmap
+infixl 5 <$$>
+
+-- | perform action corresponding to RunMode on each file
+checkFiles :: RunMode -> [FilePath] -> IO ()
+checkFiles RunModeDefault paths =
+    mapM_ (\path ->
+           checkFile path >>=
+           maybe (printf "%s: read error or not a image file\n" path)
+                     (\(s, p, w, h) ->
+                          printf "%s: %s, %s, %dx%d\n" path
+                                 (if p then "wallpaper" else "not wallpaper")
+                                 (sizeName s) w h)) paths
+checkFiles (RunModeList v) paths =
+    mapM (\path -> do
+            res <- checkFile path
+            return $ (\(_, p, _, _) ->
+                          (path, if v then not p else p)) <$> res) paths
+                   <$$> catMaybes
+                   <$$> filter snd
+                   >>= mapM_ (putStrLn . fst)
+checkFiles (RunModeSilent v) paths =
+    mapM (\path -> do
+            res <- checkFile path
+            return $ (\(_, p, _, _) ->
+                          if v then not p else p) <$> res) paths
+                   <$$> catMaybes
+                   <$$> and
+                   >>= \q -> if q then exitSuccess
+                             else exitWith (ExitFailure 1)
+
+data Opts = Help
+          | Version
+          | ListMode
+          | SilentMode
+          | InvPred
+
+options :: [OptDescr Opts]
+options = [ Option "h" ["help"]    (NoArg Help)
+                       "Show help message and exit"
+          , Option "V" ["version"] (NoArg Version)
+                       "Show version info and exit"
+          , Option "v" ["invert"]  (NoArg InvPred)
+                       "Invert filtering condition for `-l' and `-q'"
+          , Option "l" ["list"]    (NoArg ListMode)
+                       "Just list files suitable for wallpapers"
+          , Option "q" ["quiet"]   (NoArg SilentMode)
+                       "Return successful status if all images suitable" ]
+
+-- | parse commandline arguments
+getOpts :: [String] -> IO (RunMode, [String])
+getOpts argv =
+    case getOpt Permute options argv of
+      (o, n, []  ) -> foldOpts o <$$> toRunMode <$$> (\o' -> (o', n))
+      (_, _, errs) -> ioError (userError $ concat errs)
+    where foldOpts :: [Opts] -> IO (RunMode, Bool)
+          foldOpts =
+              foldM (\(m, v) e ->
+                         case e of
+                           Help       -> putStrLn usage
+                                         >> exitSuccess
+                                         >> return (m, v)
+                           Version    -> putStrLn version
+                                         >> exitSuccess
+                                         >> return (m, v)
+                           ListMode   -> return (RunModeList   False, v)
+                           SilentMode -> return (RunModeSilent False, v)
+                           InvPred    -> return (m, not v))
+                        (RunModeDefault, False)
+          toRunMode :: (RunMode, Bool) -> RunMode
+          toRunMode (m, v) = case m of
+                               RunModeDefault  -> RunModeDefault
+                               RunModeList   _ -> RunModeList   v
+                               RunModeSilent _ -> RunModeSilent v
+
+usage :: String
+usage = usageInfo "isiz [options] [files]\n\nOptions:" options
+
+version :: String
+version = "isiz version 0.0.1"
+
+main :: IO ()
+main = getArgs >>= getOpts >>= uncurry checkFiles
+
