diff --git a/ReadMe.md b/ReadMe.md
new file mode 100644
--- /dev/null
+++ b/ReadMe.md
@@ -0,0 +1,38 @@
+# Usage
+
+The most simple call is:
+~~~~
+gs-parallel input.pdf page%04d.png -j4 -- -sDEVICE=png16m -dNOPAUSE -dBATCH
+~~~~
+This converts the document `input.pdf` to a series of PNGs, one for each page.
+It splits the range of all pages in four almost equally sized ranges
+and forks a ghostscript instance for each of these ranges.
+
+
+If there is a cluster of pages that requires an especially long render time,
+then it might be useful to chop the page set into more smaller chunks.
+~~~~
+gs-parallel input.pdf page%04d.ppm -j4 --chunk-size 100 \
+    -- -sDEVICE=ppmraw -dNOPAUSE -dBATCH
+~~~~
+This will process a document with 910 pages
+in chunks of sizes 100, 100, ..., 100, 10.
+
+If you want a more balanced series of chunk sizes,
+use the option `--max-chunk-size` instead:
+~~~~
+gs-parallel input.pdf page%04d.tif -j4 --max-chunk-size 100 \
+    -- -sDEVICE=tif24nc -dNOPAUSE -dBATCH
+~~~~
+It will process 10 chunks of size 91.
+
+
+For selecting a subrange of pages,
+you must use the options `--first-page` and `--last-page`
+instead of the `gs` options `-dFirstPage` and `-dLastPage`,
+because `gs-parallel` must know the selected pages.
+
+
+# Known issues
+
+We do not escape the pdf file path for page counting, this may cause problems.
diff --git a/ghostscript-parallel.cabal b/ghostscript-parallel.cabal
--- a/ghostscript-parallel.cabal
+++ b/ghostscript-parallel.cabal
@@ -1,5 +1,5 @@
 Name:                ghostscript-parallel
-Version:             0.0
+Version:             0.0.1
 Synopsis:            Let Ghostscript render pages in parallel
 Description:
   This is intended for rendering PostScript or PDF documents using Ghostscript.
@@ -16,8 +16,7 @@
   .
   Run it like so:
   .
-  > gs-parallel input.pdf frames-%04d.png \
-  >     -- -sDEVICE=png16m -dNOPAUSE -dBATCH
+  > gs-parallel input.pdf page%04d.png -j4 -- -sDEVICE=png16m -dNOPAUSE -dBATCH
 Homepage:            https://hub.darcs.net/thielema/ghostscript-parallel
 License:             BSD3
 License-File:        LICENSE
@@ -28,9 +27,10 @@
 Cabal-Version:       >=1.10
 Extra-Source-Files:
   Makefile
+  ReadMe.md
 
 Source-Repository this
-  Tag:         0.0
+  Tag:         0.0.1
   Type:        darcs
   Location:    https://hub.darcs.net/thielema/ghostscript-parallel
 
@@ -45,6 +45,7 @@
     optparse-applicative >=0.11 && <0.19,
     directory >=1.3 && <1.4,
     process >=1.6 && <1.7,
+    non-empty >=0.3.4 && <0.4,
     utility-ht >=0.0.10 && <0.1,
     base >=4.5 && <5
   Hs-Source-Dirs:      src
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -12,12 +12,13 @@
 import System.Process (callProcess, readProcess)
 
 import qualified Data.Foldable as Fold
-import qualified Data.List.HT as ListHT
+import qualified Data.NonEmpty.Class as NonEmptyC
+import qualified Data.NonEmpty as NonEmpty
 import qualified Data.Ix as Ix
 import Data.Tuple.HT (mapSnd)
 import Data.Monoid ((<>))
 
-import Control.Applicative (pure, (<*>))
+import Control.Applicative (pure, (<*>), (<|>))
 
 import Text.Printf (printf)
 
@@ -45,18 +46,31 @@
 divUp :: (Integral a) => a -> a -> a
 divUp x y = - div (-x) y
 
+splitPages :: Int -> Int -> NonEmpty.T [] Int
+splitPages numJobs numPages =
+   fmap (flip divUp numJobs) $
+   NonEmpty.mapTail (take numJobs) $ NonEmptyC.iterate (numPages+) 0
+
+splitInChunks :: Int -> Int -> NonEmpty.T [] Int
+splitInChunks chunkSize numPages =
+   flip NonEmpty.snoc numPages $ takeWhile (<numPages) $ iterate (chunkSize+) 0
+
+splitInBoundedChunks :: Int -> Int -> NonEmpty.T [] Int
+splitInBoundedChunks chunkSize numPages =
+   splitPages (divUp numPages chunkSize) numPages
+
 run ::
    Int -> Int -> Maybe Int ->
+   (Int -> Int -> NonEmpty.T [] Int) ->
    FilePath -> FilePath -> [String] -> IO ()
-run numJobs firstPage mLastPage input output gsArgs = do
+run numJobs firstPage mLastPage split input output gsArgs = do
    lastPage <- maybe (countPages input) return mLastPage
    let num = Ix.rangeSize (firstPage, lastPage)
    let ranges =
          zip [0::Integer ..] $
-         ListHT.mapAdjacent
+         NonEmpty.mapAdjacent
             (\p0 p1 -> (p0,p1-1))
-            (map ((firstPage+) . flip divUp numJobs) $
-             take (numJobs+1) $ iterate (num+) 0)
+            (fmap (firstPage+) $ split numJobs num)
    Pool.runException (Just numJobs) $
       flip map ranges $ \(job,(p0,p1)) -> do
          callProcess "gs" $
@@ -75,30 +89,51 @@
          (printf output dstPage)
 
 
+parsePositiveNumber :: (Read a, Ord a, Num a) => String -> OP.ReadM a
+parsePositiveNumber name =
+   OP.eitherReader $ parseNumber name (0<) "positive"
+
 parser :: OP.Parser ([String] -> IO ())
 parser =
    pure run
    <*>
-      (OP.option
-            (OP.eitherReader $ parseNumber "number of jobs" (0<) "positive") $
+      (OP.option (parsePositiveNumber "number of jobs") $
          OP.short 'j' <>
          OP.long "jobs" <>
          OP.metavar "NUMBER" <>
          OP.value 1 <>
          OP.help "Number of parallel threads")
    <*>
-      (OP.option (OP.eitherReader $ parseNumber "page" (0<) "positive") $
+      (OP.option (parsePositiveNumber "page") $
          OP.long "first-page" <>
          OP.metavar "ONEBASED" <>
          OP.value 1 <>
          OP.help "First page to render")
    <*>
-      (OP.option
-            (fmap Just $ OP.eitherReader $ parseNumber "page" (0<) "positive") $
+      (OP.option (fmap Just $ parsePositiveNumber "page") $
          OP.long "last-page" <>
          OP.metavar "ONEBASED" <>
          OP.value Nothing <>
          OP.help "Last page to render")
+   <*>
+      (
+         (OP.option
+               (fmap (\chunkSize _numJobs numPages ->
+                        splitInChunks chunkSize numPages) $
+                parsePositiveNumber "number of pages") $
+            OP.long "chunk-size" <>
+            OP.metavar "NUMBER" <>
+            OP.help "Split pages into chunks of NUMBER pages, except the last chunk")
+         <|>
+         (OP.option
+               (fmap (\chunkSize _numJobs numPages ->
+                        splitInBoundedChunks chunkSize numPages) $
+                parsePositiveNumber "number of pages") $
+            OP.long "max-chunk-size" <>
+            OP.metavar "NUMBER" <>
+            OP.value splitPages <>
+            OP.help "Split pages into chunks of balanced size containing at most NUMBER pages")
+      )
    <*>
       OP.strArgument
          (OP.metavar "INPUT" <>
