hakyll-images 0.4.2 → 0.4.3
raw patch · 8 files changed
+102/−89 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +5/−1
- README.md +4/−2
- hakyll-images.cabal +9/−9
- library/Hakyll/Images/Common.hs +30/−26
- library/Hakyll/Images/CompressJpg.hs +17/−14
- library/Hakyll/Images/Resize.hs +27/−28
- package.yaml +7/−7
- tests/Hakyll/Images/Resize/Tests.hs +3/−2
CHANGELOG.md view
@@ -1,6 +1,10 @@ # Change log -## Release 0.4.2 (development) +## Release 0.4.3 + +* hakyll-images now handles file extensions in a case-insensitive manner (extension of PR #4). + +## Release 0.4.2 * Added `ensureFitCompiler`, a Hakyll compiler much like `scaleImageCompiler` but that will only scale images down.
README.md view
@@ -21,6 +21,8 @@ , scaleImageCompiler ) +(...) + hakyll $ do -- Compress all source Jpegs to a Jpeg quality of 50 (maximum of 100) @@ -35,7 +37,7 @@ route idRoute compile $ loadImage >>= resizeImageCompiler 64 48 - >>= compressJpgCompiler 50 + >>= compressJpg 50 -- Scale images to fit within a 600x400 box -- Aspect ratio will be preserved @@ -47,7 +49,7 @@ (...) ``` -Take a look at the [documentation](https://hackage.haskell.org/package/hakyll-images) for more usage examples. +Take a look at the [documentation](hackage.haskell.org/package/hakyll-images) for more usage examples. If you would like a feature added, consider creating [an issue on Github](https://github.com/LaurentRDC/hakyll-images/issues/)
hakyll-images.cabal view
@@ -1,15 +1,15 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.31.1.+-- This file has been generated from package.yaml by hpack version 0.31.2. -- -- see: https://github.com/sol/hpack ----- hash: 547b36dd9930c6d6024668fa4e252f159f4c59a719d63f0bc7c13a0d7371b642+-- hash: ff6ba07ab7468ad9c999ec58ffab35f8ef4fafb3fe2d4788536a60ef35035d8c name: hakyll-images-version: 0.4.2+version: 0.4.3 synopsis: Hakyll utilities to work with images-description: hakyll-images is an add-on to the hakyll package. It adds utilities to work with images, including JPEG compression, image scaling, and more.+description: hakyll-images is an add-on to the hakyll package. It adds utilities to work with images, including JPEG compression. category: Web homepage: https://github.com/LaurentRDC/hakyll-images#readme bug-reports: https://github.com/LaurentRDC/hakyll-images/issues@@ -68,16 +68,16 @@ library ghc-options: -Wall -Wcompat build-depends:- HUnit-approx >=1.0.0.0+ HUnit-approx >=1 && <2 , JuicyPixels >=3 , JuicyPixels-extra >0.3 , base >=4.8 && <5 , binary >=0.5 && <0.10 , bytestring >=0.9 && <0.11- , directory >=1.0- , filepath >=1.0 && <1.5+ , directory >=1 && <2+ , filepath >=1 && <2 , hakyll >4 , hakyll-images- , tasty >=0.11 && <1.2- , tasty-hunit >=0.9 && <0.11+ , tasty >=0.11 && <2+ , tasty-hunit >=0.9 && <1 default-language: Haskell2010
library/Hakyll/Images/Common.hs view
@@ -1,7 +1,7 @@+{-# LANGUAGE TypeSynonymInstances #-} +{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE TypeSynonymInstances #-} {-| Module : Hakyll.Images.Common Description : Types and utilities for Hakyll.Images @@ -18,25 +18,25 @@ , encode ) where -import Prelude hiding (readFile) +import Prelude hiding (readFile) -import Codec.Picture.Saving -import Codec.Picture.Types (DynamicImage) +import Codec.Picture.Types (DynamicImage) +import Codec.Picture.Saving -import Data.Binary (Binary (..)) -import Data.ByteString (ByteString) -import Data.ByteString.Lazy (toStrict) -import Data.Typeable (Typeable) -import GHC.Generics (Generic) +import Data.Binary (Binary(..)) +import Data.ByteString.Lazy (toStrict) +import Data.ByteString (ByteString) +import Data.Char (toLower) +import Data.Typeable (Typeable) +import GHC.Generics (Generic) -import Hakyll.Core.Compiler (Compiler, getResourceLBS, - getUnderlyingExtension) -import Hakyll.Core.Item (Item (..)) -import Hakyll.Core.Writable (Writable (..)) +import Hakyll.Core.Compiler (Compiler, getResourceLBS, getUnderlyingExtension) +import Hakyll.Core.Item (Item(..)) +import Hakyll.Core.Writable (Writable(..)) -- Supported (i.e. encodable) image formats data ImageFormat - = Jpeg + = Jpeg | Png | Bitmap | Tiff @@ -48,7 +48,7 @@ -- Polymorphic type only to get an instance of functor. -- Do not use this type. data Image = Image { format :: ImageFormat - , image :: ByteString + , image :: ByteString } deriving (Typeable) @@ -69,7 +69,7 @@ -- @ -- match "*.jpg" $ do -- route idRoute --- compile $ loadImage +-- compile $ loadImage -- >>= compressJpgCompiler 50 -- @ loadImage :: Compiler (Item Image) @@ -80,19 +80,23 @@ -- | Translation between file extensions and image formats. -- It is important to keep track of image formats because Hakyll --- compilers provides raw bytestrings and filenames +-- compilers provides raw bytestrings and filenames. +-- +-- This function is case-insensitive fromExt :: String -> ImageFormat -fromExt ".jpeg" = Jpeg -fromExt ".jpg" = Jpeg -fromExt ".png" = Png -fromExt ".bmp" = Bitmap -fromExt ".tif" = Tiff -fromExt ".tiff" = Tiff -fromExt ext = error $ "Unsupported format: " <> ext +fromExt ext = fromExt' $ toLower <$> ext + where + fromExt' ".jpeg" = Jpeg + fromExt' ".jpg" = Jpeg + fromExt' ".png" = Png + fromExt' ".bmp" = Bitmap + fromExt' ".tif" = Tiff + fromExt' ".tiff" = Tiff + fromExt' ext' = error $ "Unsupported format: " <> ext' -- Encode images based on file extension encode :: ImageFormat -> DynamicImage -> Image encode Jpeg im = Image Jpeg $ (toStrict . imageToJpg 100) im encode Png im = Image Png $ (toStrict . imageToPng) im encode Bitmap im = Image Bitmap $ (toStrict . imageToBitmap) im -encode Tiff im = Image Tiff $ (toStrict . imageToTiff) im +encode Tiff im = Image Tiff $ (toStrict . imageToTiff) im
library/Hakyll/Images/CompressJpg.hs view
@@ -19,7 +19,7 @@ import Hakyll.Images ( loadImage , compressJpgCompiler ) - + hakyll $ do -- Compress all source Jpegs to a Jpeg quality of 50 @@ -27,7 +27,7 @@ route idRoute compile $ loadImage >>= compressJpgCompiler 50 - + (... omitted ...) @ -} @@ -37,16 +37,19 @@ , compressJpg ) where -import Data.ByteString.Lazy (toStrict) +import Data.ByteString.Lazy (toStrict) -import Codec.Picture.Jpg (decodeJpeg) -import Codec.Picture.Saving (imageToJpg) +import Codec.Picture.Jpg (decodeJpeg) +import Codec.Picture.Saving (imageToJpg) -import Hakyll.Core.Compiler (Compiler) -import Hakyll.Core.Item (Item (..)) +import Hakyll.Core.Item (Item(..)) +import Hakyll.Core.Compiler (Compiler) -import Hakyll.Images.Common (Image (..), ImageFormat (..), format, - image) +import Hakyll.Images.Common ( Image(..) + , ImageFormat(..) + , image + , format + ) -- | Jpeg encoding quality, from 0 (lower quality) to 100 (best quality). @@ -55,15 +58,15 @@ -- | Compress a JPG bytestring to a certain quality setting. -- The quality should be between 0 (lowest quality) and 100 (best quality). --- An error is raised if the image cannot be decoded, or if the +-- An error is raised if the image cannot be decoded, or if the -- encoding quality is out-of-bounds compressJpg :: JpgQuality -> Image -> Image compressJpg quality src = if (format src) /= Jpeg then error $ "Image is not a JPEG." - else + else case decodeJpeg $ image src of Left _ -> error $ "Loading the image failed." - Right dynImage -> + Right dynImage -> if (quality < 0 || quality > 100) then error $ "JPEG encoding quality should be between 0 and 100." else Image Jpeg $ (toStrict $ imageToJpg quality dynImage) @@ -75,8 +78,8 @@ -- @ -- match "*.jpg" $ do -- route idRoute --- compile $ loadImage +-- compile $ loadImage -- >>= compressJpgCompiler 50 -- @ compressJpgCompiler :: JpgQuality -> Item Image -> Compiler (Item Image) -compressJpgCompiler quality item = return $ compressJpg quality <$> item +compressJpgCompiler quality item = return $ compressJpg quality <$> item
library/Hakyll/Images/Resize.hs view
@@ -8,19 +8,19 @@ Stability : unstable Portability : portable -This module defines two Hakyll compilers. The first one, 'resizeImageCompiler', +This module defines two Hakyll compilers. The first one, 'resizeImageCompiler', is used to resize images to specific dimensions. The aspect ratio might not be the same. -The other compiler, `scaleImageCompiler`, scales images to fit within a specified +The other compiler, `scaleImageCompiler`, scales images to fit within a specified box while preserving aspect ratio. @ import Hakyll import Hakyll.Images ( loadImage - , resizeImageCompiler + , resizeImageCompiler , scaleImageCompiler ) - + hakyll $ do -- Resize all profile pictures with .png extensions to 64x48 @@ -28,13 +28,13 @@ route idRoute compile $ loadImage >>= resizeImageCompiler 64 48 - + -- Scale images to fit within a 600x400 box match "images/**" $ do route idRoute compile $ loadImage >>= scaleImageCompiler 600 400 - + (... omitted ...) @ -} @@ -48,26 +48,25 @@ , ensureFitCompiler ) where -import Codec.Picture (convertRGBA8, decodeImage) -import Codec.Picture.Extra (scaleBilinear) -import Codec.Picture.Types (DynamicImage (..), imageHeight, - imageWidth) +import Codec.Picture (convertRGBA8, decodeImage) +import Codec.Picture.Types (DynamicImage(..), imageHeight, imageWidth) +import Codec.Picture.Extra (scaleBilinear) -import Data.ByteString (ByteString) -import Data.Ratio ((%)) +import Data.ByteString (ByteString) +import Data.Ratio ((%)) -import Hakyll.Core.Compiler (Compiler) -import Hakyll.Core.Item (Item (..)) +import Hakyll.Core.Item (Item(..)) +import Hakyll.Core.Compiler (Compiler) -import Hakyll.Images.Common (Image (..), encode) +import Hakyll.Images.Common (Image(..), encode) type Width = Int type Height = Int decodeImage' :: ByteString -> DynamicImage decodeImage' im = case decodeImage im of - Left msg -> error msg - Right im' -> im' + Left msg -> error msg + Right im' -> im' -- | Resize an image to specified width and height using the bilinear transform. -- The aspect ratio may not be respected. @@ -79,7 +78,7 @@ -- | Scale an image to a size that will fit in the specified width and height, -- while preserving aspect ratio. Images might be scaled up as well. --- +-- -- In the process, an image is converted to RGBA8. Therefore, some information -- loss may occur. -- @@ -89,7 +88,7 @@ -- | Scale an image to a size that will fit in the specified width and height, -- while preserving aspect ratio. Images might be scaled up as well. --- +-- -- In the process, an image is converted to RGBA8. Therefore, some information -- loss may occur. scale' :: Width -- ^ Desired width. @@ -101,10 +100,10 @@ where img' = convertRGBA8 img -- Required to extract height and width (imgWidth, imgHeight) = (imageWidth img', imageHeight img') - -- Find the smallest resizing that will accomodate both the width + -- Find the smallest resizing that will accomodate both the width -- and height. -- If we don't allow scaling up, minimum scaling is 1 - resizing = if upAllowed + resizing = if upAllowed then min (w % imgWidth) (h % imgHeight) else minimum [w % imgWidth, h % imgHeight, 1] maxWidth = round (resizing * fromIntegral imgWidth) @@ -112,7 +111,7 @@ -- | Scale an image down to a size that will fit in the specified width and height, -- while preserving aspect ratio. --- +-- -- In the process, an image is converted to RGBA8. Therefore, some information -- loss may occur. -- @@ -126,7 +125,7 @@ -- @ -- match "*.png" $ do -- route idRoute --- compile $ loadImage +-- compile $ loadImage -- >>= resizeImageCompiler 48 64 -- @ -- @@ -143,7 +142,7 @@ -- @ -- match "*.tiff" $ do -- route idRoute --- compile $ loadImage +-- compile $ loadImage -- >>= scaleImageCompiler 48 64 -- @ -- @@ -154,19 +153,19 @@ let fmt = (format . itemBody) item in return $ (encode fmt . scale w h . decodeImage' . image) <$> item --- | Compiler that ensures images will fit within dimensions. Images might +-- | Compiler that ensures images will fit within dimensions. Images might -- be scaled down, but never up. Aspect ratio will be preserved. -- -- @ -- match "*.tiff" $ do -- route idRoute --- compile $ loadImage +-- compile $ loadImage -- >>= ensureFitCompiler 48 64 -- @ -- -- Note that in the resizing process, images will be converted to RGBA8. -- To allow the possibility of scaling up, take a look at 'scaleImageCompiler'. ensureFitCompiler :: Width -> Height -> Item Image -> Compiler (Item Image) -ensureFitCompiler w h item = +ensureFitCompiler w h item = let fmt = (format . itemBody) item - in return $ (encode fmt . ensureFit w h . decodeImage' . image) <$> item + in return $ (encode fmt . ensureFit w h . decodeImage' . image) <$> item
package.yaml view
@@ -1,5 +1,5 @@ name: hakyll-images -version: '0.4.2' +version: '0.4.3' github: "LaurentRDC/hakyll-images" license: BSD3 author: "Laurent P. René de Cotret" @@ -7,7 +7,7 @@ synopsis: "Hakyll utilities to work with images" description: hakyll-images is an add-on to the hakyll package. It adds utilities to work - with images, including JPEG compression, image scaling, and more. + with images, including JPEG compression. category: Web license-file: LICENSE.md @@ -45,11 +45,11 @@ main: TestSuite.hs dependencies: - hakyll-images - - tasty >= 0.11 && < 1.2 - - tasty-hunit >= 0.9 && < 0.11 - - HUnit-approx >= 1.0.0.0 - - filepath >= 1.0 && < 1.5 - - directory >= 1.0 + - tasty >= 0.11 && < 2 + - tasty-hunit >= 0.9 && < 1 + - HUnit-approx >= 1 && < 2 + - filepath >= 1 && < 2 + - directory >= 1 && < 2 # Base hakyll-images dependencies - base >= 4.8 && < 5 - binary >= 0.5 && < 0.10
tests/Hakyll/Images/Resize/Tests.hs view
@@ -54,8 +54,9 @@ (width, height) = ( imageWidth converted , imageHeight converted ) - assertEqual "Image width was not scaled properly" width 600 - assertBool "Image height was not scaled property" (height<= 400) + assertBool "Image width was not scaled properly" (width <= 600) + assertBool "Image height was not scaled properly" (height<= 400) + assertBool "Image overall was not scaled properly" (width == 600 || height == 400) -- Test that the images that already fit in dimensions are not scaled testEnsureFit :: Assertion