diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,3 @@
+## FLAC Picture 0.1.0
+
+* Initial release.
diff --git a/Codec/Audio/FLAC/Metadata/Picture.hs b/Codec/Audio/FLAC/Metadata/Picture.hs
new file mode 100644
--- /dev/null
+++ b/Codec/Audio/FLAC/Metadata/Picture.hs
@@ -0,0 +1,73 @@
+-- |
+-- Module      :  Codec.Audio.FLAC.Metadata.Picture
+-- Copyright   :  © 2017 Mark Karpov
+-- License     :  BSD 3 clause
+--
+-- Maintainer  :  Mark Karpov <markkarpov@openmailbox.org>
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- Juicy-Pixels-powered helpers to read\/write images to FLAC metadata
+-- blocks. For maximal player support, use PNG or JPEG (we don't provide
+-- helpers for other formats at the time anyway).
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Codec.Audio.FLAC.Metadata.Picture
+  ( retrieveImage
+  , writeJpegPicture
+  , writePngPicture )
+where
+
+import Codec.Audio.FLAC.Metadata
+import Codec.Picture
+import Data.Word
+import qualified Data.ByteString.Lazy as BL
+
+-- | Read specific picture from FLAC metadata as 'DynamicImage'.
+
+retrieveImage
+  :: PictureType
+  -> FlacMeta (Either String DynamicImage)
+retrieveImage pictureType = do
+  mpicture <- retrieve (Picture pictureType)
+  case mpicture of
+    Nothing -> return (Left "Picture not found")
+    Just picture -> (return . decodeImage . pictureData) picture
+
+-- | Write the given image into FLAC metadata block corresponding to
+-- specific 'PictureType'.
+
+writeJpegPicture
+  :: PictureType       -- ^ Type of picture we're writing
+  -> Word8             -- ^ Quality factor, see 'encodeJpegAtQuality'
+  -> Image PixelYCbCr8 -- ^ The picture to write
+  -> FlacMeta ()
+writeJpegPicture pictureType q image =
+  Picture pictureType =-> Just PictureData
+    { pictureMimeType    = "image/jpeg"
+    , pictureDescription = ""
+    , pictureWidth       = fromIntegral (imageWidth image)
+    , pictureHeight      = fromIntegral (imageHeight image)
+    , pictureDepth       = 24
+    , pictureColors      = 0 -- non-indexed
+    , pictureData        = BL.toStrict (encodeJpegAtQuality q image)
+    }
+
+-- | Write the given image into FLAC metadata block corresponding to
+-- specific 'PictureType'.
+
+writePngPicture
+  :: PictureType       -- ^ Type of picture we're writing
+  -> Image PixelRGB8   -- ^ The picture to write
+  -> FlacMeta ()
+writePngPicture pictureType image =
+  Picture pictureType =-> Just PictureData
+    { pictureMimeType    = "image/png"
+    , pictureDescription = ""
+    , pictureWidth       = fromIntegral (imageWidth image)
+    , pictureHeight      = fromIntegral (imageHeight image)
+    , pictureDepth       = 24
+    , pictureColors      = 0 -- non-indexed
+    , pictureData        = BL.toStrict (encodePng image)
+    }
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,28 @@
+Copyright © 2017 Mark Karpov
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+
+* 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.
+
+* Neither the name Mark Karpov nor the names of contributors may be used to
+  endorse or promote products derived from this software without specific
+  prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS “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 COPYRIGHT HOLDERS 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,17 @@
+# FLAC Picture
+
+[![License BSD3](https://img.shields.io/badge/license-BSD3-brightgreen.svg)](http://opensource.org/licenses/BSD-3-Clause)
+[![Hackage](https://img.shields.io/hackage/v/flac-picture.svg?style=flat)](https://hackage.haskell.org/package/flac-picture)
+[![Stackage Nightly](http://stackage.org/package/flac-picture/badge/nightly)](http://stackage.org/nightly/package/flac-picture)
+[![Stackage LTS](http://stackage.org/package/flac-picture/badge/lts)](http://stackage.org/lts/package/flac-picture)
+[![Build Status](https://travis-ci.org/mrkkrp/flac-picture.svg?branch=master)](https://travis-ci.org/mrkkrp/flac-picture)
+[![Coverage Status](https://coveralls.io/repos/mrkkrp/flac-picture/badge.svg?branch=master&service=github)](https://coveralls.io/github/mrkkrp/flac-picture?branch=master)
+
+I bet you always wanted to write a picture into FLAC metadata blocks. I'll
+tell you what, with **Haskell** you can do it.
+
+## License
+
+Copyright © 2017 Mark Karpov
+
+Distributed under BSD 3 clause license.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,6 @@
+module Main (main) where
+
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMain
diff --git a/audio-samples/sample.flac b/audio-samples/sample.flac
new file mode 100644
Binary files /dev/null and b/audio-samples/sample.flac differ
diff --git a/flac-picture.cabal b/flac-picture.cabal
new file mode 100644
--- /dev/null
+++ b/flac-picture.cabal
@@ -0,0 +1,91 @@
+--
+-- Cabal configuration for ‘flac-picture’ package.
+--
+-- Copyright © 2017 Mark Karpov <markkarpov@openmailbox.org>
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are
+-- met:
+--
+-- * Redistributions of source code must retain the above copyright notice,
+--   this list of conditions and the following disclaimer.
+--
+-- * 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.
+--
+-- * Neither the name Mark Karpov nor the names of contributors may be used
+--   to endorse or promote products derived from this software without
+--   specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS “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 COPYRIGHT HOLDERS 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.
+
+name:                 flac-picture
+version:              0.1.0
+cabal-version:        >= 1.10
+license:              BSD3
+license-file:         LICENSE.md
+author:               Mark Karpov <markkarpov@openmailbox.org>
+maintainer:           Mark Karpov <markkarpov@openmailbox.org>
+homepage:             https://github.com/mrkkrp/flac-picture
+bug-reports:          https://github.com/mrkkrp/flac-picture/issues
+category:             Codec, Audio, Image
+synopsis:             Support for writing picture to FLAC metadata blocks with JuicyPixels
+build-type:           Simple
+description:          Support for writing picture to FLAC metadata blocks with JuicyPixels.
+extra-doc-files:      CHANGELOG.md
+                    , README.md
+data-files:           audio-samples/*.flac
+                    , picture-samples/*.jpeg
+                    , picture-samples/*.png
+
+source-repository head
+  type:               git
+  location:           https://github.com/mrkkrp/flac-picture.git
+
+flag dev
+  description:        Turn on development settings.
+  manual:             True
+  default:            False
+
+library
+  build-depends:      JuicyPixels      >= 3.2.6.5 && < 4.0
+                    , base             >= 4.7 && < 5.0
+                    , bytestring       >= 0.2 && < 0.11
+                    , flac             >= 0.1 && < 0.2
+  exposed-modules:    Codec.Audio.FLAC.Metadata.Picture
+  if flag(dev)
+    ghc-options:      -Wall -Werror
+  else
+    ghc-options:      -O2 -Wall
+  default-language:   Haskell2010
+
+test-suite tests
+  main-is:            Spec.hs
+  other-modules:      Codec.Audio.FLAC.Metadata.PictureSpec
+  hs-source-dirs:     tests
+  type:               exitcode-stdio-1.0
+  build-depends:      JuicyPixels      >= 3.2.6.5 && < 4.0
+                    , base             >= 4.7 && < 5.0
+                    , bytestring       >= 0.2 && < 0.11
+                    , data-default-class
+                    , directory        >= 1.2.2 && < 1.3
+                    , flac             >= 0.1 && < 0.2
+                    , flac-picture     >= 0.1.0
+                    , hspec            >= 2.0 && < 3.0
+                    , temporary        >= 1.1 && < 1.3
+  if flag(dev)
+    ghc-options:      -Wall -Werror
+  else
+    ghc-options:      -O2 -Wall
+  default-language:   Haskell2010
diff --git a/picture-samples/lenna.jpeg b/picture-samples/lenna.jpeg
new file mode 100644
Binary files /dev/null and b/picture-samples/lenna.jpeg differ
diff --git a/picture-samples/lenna.png b/picture-samples/lenna.png
new file mode 100644
Binary files /dev/null and b/picture-samples/lenna.png differ
diff --git a/tests/Codec/Audio/FLAC/Metadata/PictureSpec.hs b/tests/Codec/Audio/FLAC/Metadata/PictureSpec.hs
new file mode 100644
--- /dev/null
+++ b/tests/Codec/Audio/FLAC/Metadata/PictureSpec.hs
@@ -0,0 +1,105 @@
+--
+-- Tests for the ‘flac-picture’ package.
+--
+-- Copyright © 2017 Mark Karpov <markkarpov@openmailbox.org>
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are
+-- met:
+--
+-- * Redistributions of source code must retain the above copyright notice,
+--   this list of conditions and the following disclaimer.
+--
+-- * 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.
+--
+-- * Neither the name Mark Karpov nor the names of contributors may be used
+--   to endorse or promote products derived from this software without
+--   specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS “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 COPYRIGHT HOLDERS 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.
+
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
+
+module Codec.Audio.FLAC.Metadata.PictureSpec
+  ( spec )
+where
+
+import Codec.Audio.FLAC.Metadata
+import Codec.Audio.FLAC.Metadata.Picture
+import Codec.Picture
+import Control.Monad
+import Data.Default.Class
+import Data.Function (on)
+import System.Directory
+import System.IO
+import System.IO.Temp (withSystemTempFile)
+import Test.Hspec
+import qualified Data.ByteString.Lazy as BL
+
+spec :: Spec
+spec = around withSandbox $ do
+  describe "writeJpegPicture/retrieveImage" . forM_ [minBound..maxBound] $ \ptype ->
+    it ("writes JPEG picture and reads it back: " ++ show ptype) $ \path -> do
+      Right (ImageYCbCr8 pic) <- readJpeg "picture-samples/lenna.jpeg"
+      runFlacMeta def path (writeJpegPicture ptype 127 pic)
+      let Right (ImageYCbCr8 pic'') = (decodeJpeg . BL.toStrict)
+            (encodeJpegAtQuality 100 pic)
+      Just PictureData {..} <- runFlacMeta def path (retrieve $ Picture ptype)
+      pictureMimeType `shouldBe` "image/jpeg"
+      pictureDescription `shouldBe` ""
+      pictureWidth `shouldBe` fromIntegral (imageWidth pic)
+      pictureHeight `shouldBe` fromIntegral (imageHeight pic)
+      pictureDepth `shouldBe` 24
+      pictureColors `shouldBe` 0
+      Right (ImageYCbCr8 pic') <- runFlacMeta def path (retrieveImage ptype)
+      pic' `imageShouldBe` pic''
+  describe "writePngPicture/retrieveImage" . forM_ [minBound..maxBound] $ \ptype ->
+    it ("writes PNG picture and reads it back: " ++ show ptype) $ \path -> do
+      Right (ImageRGB8 pic) <- readPng "picture-samples/lenna.png"
+      runFlacMeta def path (writePngPicture ptype pic)
+      Just PictureData {..} <- runFlacMeta def path (retrieve $ Picture ptype)
+      pictureMimeType `shouldBe` "image/png"
+      pictureDescription `shouldBe` ""
+      pictureWidth `shouldBe` fromIntegral (imageWidth pic)
+      pictureHeight `shouldBe` fromIntegral (imageHeight pic)
+      pictureDepth `shouldBe` 24
+      pictureColors `shouldBe` 0
+      Right (ImageRGB8 pic') <- runFlacMeta def path (retrieveImage ptype)
+      pic' `imageShouldBe` pic
+
+----------------------------------------------------------------------------
+-- Helpers
+
+-- | Make a temporary copy of @audio-samples/sample.flac@ file and provide
+-- the path to the file. Automatically remove the file when the test
+-- finishes.
+
+withSandbox :: ActionWith FilePath -> IO ()
+withSandbox action = withSystemTempFile "sample.flac" $ \path h -> do
+  hClose h
+  copyFile "audio-samples/sample.flac" path
+  action path
+
+imageShouldBe
+  :: (Pixel a, Show (PixelBaseComponent a), Eq (PixelBaseComponent a))
+  => Image a
+  -> Image a
+  -> Expectation
+imageShouldBe img0 img1 = do
+  (shouldBe `on` imageWidth)  img0 img1
+  (shouldBe `on` imageHeight) img0 img1
+  (shouldBe `on` imageData)   img0 img1
diff --git a/tests/Spec.hs b/tests/Spec.hs
new file mode 100644
--- /dev/null
+++ b/tests/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
