packages feed

pixelated-avatar-generator 0.1.2 → 0.1.3

raw patch · 5 files changed

+113/−56 lines, 5 filesdep +asyncdep +clidep +randomPVP ok

version bump matches the API change (PVP)

Dependencies added: async, cli, random

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Changelog +## 0.1.3+* Create new executable program.+* Make several small internal fixes.+* Add badges for Hackage and Stackage to readme.+ ## 0.1.2 * Add missing test files to Cabal config, to allow tests to pass from Hackage package. 
README.md view
@@ -1,4 +1,4 @@-# Pixelated Avatar Generator [![Travis CI Status](https://api.travis-ci.org/ExcaliburZero/pixelated-avatar-generator.svg)](https://travis-ci.org/ExcaliburZero/pixelated-avatar-generator) [![Coverage Status](https://coveralls.io/repos/github/ExcaliburZero/pixelated-avatar-generator/badge.svg?branch=master)](https://coveralls.io/github/ExcaliburZero/pixelated-avatar-generator?branch=master)+# Pixelated Avatar Generator [![Travis CI Status](https://api.travis-ci.org/ExcaliburZero/pixelated-avatar-generator.svg)](https://travis-ci.org/ExcaliburZero/pixelated-avatar-generator) [![Coverage Status](https://coveralls.io/repos/github/ExcaliburZero/pixelated-avatar-generator/badge.svg?branch=master)](https://coveralls.io/github/ExcaliburZero/pixelated-avatar-generator?branch=master) [![Hackage](https://img.shields.io/hackage/v/pixelated-avatar-generator.svg)](https://hackage.haskell.org/package/pixelated-avatar-generator) [![pixelated-avatar-generator on Stackage Nightly](https://www.stackage.org/package/pixelated-avatar-generator/badge/nightly)](http://stackage.org/nightly/package/pixelated-avatar-generator) Pixelated Avatar Generator is a Haskell library and application for generating pixelated avatar images from seed values.  ```haskell@@ -33,41 +33,36 @@ ```  ## Executable-An example executable program that uses the library is also provided. It creates an avatar from a given seed string and saves the created `.png` image to a given file location.+An executable program for generating avatar image files is also provided. It can generate several avatar images concurrently to given file locations. -The executable can be compiled by running the following command:+The executable can be installed along with the library by running the following command:  ```-$ stack build+$ stack install pixelated-avatar-generator ``` -The executable can then by run by running it with `stack exec` and providing it the desired filepath of the output file including the `.png` extension and a random seed string.+The executable can then by run by calling it with the desired filepath(s) of the output file(s) including the `.png` extension.  ```-$ stack exec pixelated-avatar-generator image.png "Hello, World"-Creating avatar at image.png-Grey-█ ████ █-        -  ████  -█  ██  █-████████-█ █  █ █-█      █-████████-Successfully created avatar, and saved it to image.png+$ pixelated-avatar-generator image1.png image2.png+Successfully created 2 avatars. ``` +By default, the avatars are at a size of 256x256px. Though the size can be changed by using a custom scaling factor via the `--scaling-factor` flag.+ ### Usage ```-Usage: pixelated-avatar-generator FILEPATH SEEDSTRING+Usage: pixelated-avatar-generator FILEPATH_1 [FILEPATH_2] [FILEPATH_3] ... -FILEPATH   -- The location to save the generated avatar at. "img/test.png"-SEEDSTRING -- The string to use to generate the avatar. "Hello"-```+FILEPATH_(1...)   -- The locations to save generated avatars at. "img/test.png" -## Links-* [Pixelated Avatar Generator package on Hackage](https://hackage.haskell.org/package/pixelated-avatar-generator)+Options:++     --scaling-factor+         Use a custom scaling factor. The scaling factor is multiplied by 8 to+         get the dimensions of the image. For example, a scaling factor of 4+         would yield a 32x32px image. The default scaling factor is 32.+```  ## License The source code of Pixelated Avatar Generator is available under the [MIT license](https://opensource.org/licenses/MIT), see `LICENSE` for more information.
app/Main.hs view
@@ -1,35 +1,89 @@ module Main where +import Console.Options+import Control.Concurrent.Async (mapConcurrently)+import Data.Char (isDigit)+import Data.List (nub)+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>))+import Data.Version (makeVersion) import Graphics.Avatars.Pixelated-import System.Environment (getArgs)+import System.Random (randomIO)  main :: IO ()-main = do-  args <- getArgs-  checkForProperArgs args-  let path = head args-  let seedString = args !! 1-  putStrLn $ "Creating avatar at " ++ path-  createAndSaveAvatar path seedString-  putStrLn $ "Successfully created avatar, and saved it to " ++ path+main = defaultMain $ do+  -- Define program information+  programName "pixelated-avatar-generator"+  programDescription "Generates pixelated avatar images"+  programVersion $ makeVersion [0,1,2] -checkForProperArgs :: [String] -> IO ()-checkForProperArgs args = if length args /= 2-                          then error $ "Improper number of arguments.\n\n" ++ usageInfo-                          else return ()+  -- Gather program flags and arguments+  flagS <- flagParam+    (FlagLong "scaling-factor" <> FlagDescription scalingFlagDescription)+    (FlagRequired scaleParser)+  firstFile <- argument "FILEPATH" Right+  tailFiles <- remainingArguments "FILEPATHS" -usageInfo :: String-usageInfo = unlines [-     "Usage: pixelated-avatar-generator FILEPATH SEEDSTRING"-   , ""-   , "FILEPATH   -- The location to save the generated avatar at. \"img/test.png\""-   , "SEEDSTRING -- The string to use to generate the avatar. \"Hello\""+  -- Perform the functionality of the program+  action $ \toParam -> do+    let scalingFactor = fromMaybe defaultScalingFactor (toParam flagS)+    let paths = nub $ toParam firstFile : toParam tailFiles+    _ <- mapConcurrently (saveRandomAvatar scalingFactor) paths+    putStrLn $ createSuccessMessage paths++-- | The default avatar scaling factor that is used when the user does not+-- specify a custom scaling factor via the "--scaling-factor" flag.+defaultScalingFactor :: Int+defaultScalingFactor = 32++-- | The description of the "--scaling-factor" flag.+scalingFlagDescription :: String+scalingFlagDescription = unwords+  [ "Use a custom scaling factor. The scaling factor is multiplied by 8 to get"+  , "the dimensions of the image. For example, a scaling factor of 4 would"+  , "yield a 32x32px image. The default scaling factor is 32."   ] -createAndSaveAvatar :: FilePath -> String -> IO ()-createAndSaveAvatar path s = do-  let seed = createSeed s+-- | Prints a success message noting the number of images created.+--+-- >>> createSuccessMessage ["1.png", "2.png"]+-- "Successfully created 2 avatars."+createSuccessMessage :: [FilePath] -> String+createSuccessMessage paths = message+  where+    message = unwords ["Successfully created", numberOfAvatars, "avatars."]+    numberOfAvatars = (show . length) paths++-- | Creates and saves a random avatar at the given filepath using the given+-- scaling factor.+saveRandomAvatar :: Int -> FilePath -> IO ()+saveRandomAvatar factor path = do+  seed <- show <$> (randomIO :: IO Double)+  saveCustomAvatar factor path seed++-- | Creates and saves an avatar at the given filepath using the given seed+-- string and the given scaling factor.+saveCustomAvatar :: Int -> FilePath -> String -> IO ()+saveCustomAvatar factor path string = do+  let seed = createSeed string   let avatar = generateAvatar seed-  print avatar-  let avatarScaled = scaleAvatar 32 avatar+  let avatarScaled = scaleAvatar factor avatar   saveAvatar avatarScaled path++-- | Attempts to parse a scaling factor, which must be a non-positive integer+-- (1, 2, 3, ...).+--+-- >>> scaleParser "1"+-- Right 1+-- >>> scaleParser "0"+-- Left "The given String is not a positive integer"+-- >>> scaleParser "-1"+-- Left "The given String is not a positive integer"+scaleParser :: String -> Either String Int+scaleParser string+    | isPosInt string = Right ((read :: String -> Int) string)+    | otherwise       = Left "The given String is not a positive integer"+  where+    isPosInt s   = isNaturalNum s && isNotZero s+    isNaturalNum = all isDigit+    isNotZero s  = not $ all (== '0') s
pixelated-avatar-generator.cabal view
@@ -1,5 +1,5 @@ name:                pixelated-avatar-generator-version:             0.1.2+version:             0.1.3 synopsis:            A library and application for generating pixelated avatars. description:                     <<data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA1AAAACABAMAAAD345WwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AcREioaDb4fhAAAABVQTFRFKSkpaLb/lpaW0JT//4xB/+eU////Sm1svwAAAeBJREFUeNrt2bFxwzAQBEC2oBbUglpwC2zB/ZfgRHbwMzf/oKUAmr0M4IHg/IY87iXfz6zu13w1SefOZ9J62nuE1PdMezVHSde//TMHKFCgQIECBQoUKFCgQIECBQoUKFCgQIECBQrUh0GlpP4UZNpLEFPIlFWQCtNBJbg6+NV9UKBAgQIFChQoUKBAgQIFChQoUKBAgQIFChSo3aGmH1zBKkAHknod0BQywXRQHdyxmPSeVai/+0GBAgUKFChQoECBAgUKFChQoECBAgUKFChQoDaF6gC6/ZoOKIEliA6qA7qaV0N1QB0YKFCgQIECBQoUKFCgQIECBQoUKFCgQIECBQrUrlD3kg4i9evgp0B1XQd/NknnusF3sB3U6vMENu2BAgUKFChQoECBAgUKFChQoECBAgUKFChQoEB9CtRq6gV18Cmp1wFMe1OgBFYBrsLVwV8NKFCgQIECBQoUKFCgQIECBQoUKFCgQIECBQrU7lD1og4k7SeQKeBZcrX/CEkw7/5x+DvwtO56oECBAgUKFChQoECBAgUKFChQoECBAgUKFChQu0JNAVZhOqjpj8MpYAfbQaVzdfBHk3TuFpKgakCBAgUKFChQoECBAgUKFChQoECBAgUKFChQoDaF+gF8d9lnmZmUZAAAAABJRU5ErkJggg==>>@@ -44,6 +44,9 @@   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall   build-depends:       base                      , pixelated-avatar-generator+                     , cli >= 0.1.2+                     , random >= 1.0.0.2+                     , async >= 2.0.2   default-language:    Haskell2010  test-suite unit-tests
src/Graphics/Avatars/Pixelated.hs view
@@ -62,9 +62,9 @@ import Codec.Picture (encodeColorReducedGifImage, encodePng, encodeTiff, generateImage, Image(..), PixelRGB8(..)) import Data.Char (ord) import qualified Data.ByteString.Lazy as B (ByteString, writeFile)-import Data.ByteString.Lazy.Internal (packChars) import Data.Digest.Pure.MD5 (md5) import Data.List.Split (chunksOf)+import Data.String (fromString)  ------------------------------------------------------------------------------- -- Seeds@@ -81,7 +81,7 @@ -- >>> createSeed "Hello" -- Seed {unSeed = "8b1a9953c4611296a827abf8c47804d7"} createSeed :: String -> Seed-createSeed = Seed . show . md5 . packChars+createSeed = Seed . show . md5 . fromString  ------------------------------------------------------------------------------- -- Avatars@@ -100,7 +100,7 @@  -- | Generates a String containing the color and pattern of the avatar. instance Show Avatar where-  show a = (show . color) a ++ "\n" ++ ((show . grid) a)+  show a = (show . color) a ++ "\n" ++ (show . grid) a  -- | Generates an avatar from the given seed. --@@ -129,7 +129,7 @@ -- into a 32x32px avatar. scaleAvatar :: Int -> Avatar -> Avatar scaleAvatar factor avatar = avatar { grid = AvatarGrid scaledGrid }-  where scaledGrid = ((scaleList factor) . (map (scaleList factor))) unscaledGrid+  where scaledGrid = (scaleList factor . map (scaleList factor)) unscaledGrid         unscaledGrid = unAvatarGrid $ grid avatar  -- | Saves the given avatar as a png image file to the given file path. The@@ -238,14 +238,14 @@  -- | Converts the grid into a String representation. instance Show AvatarGrid where-  show x = (showGrid . unAvatarGrid) x+  show = showGrid . unAvatarGrid  -- | The left half of an AvatarGrid. newtype AvatarGridSide = AvatarGridSide { unAvatarGridSide :: [[Bool]] }  -- | Converts the grid side into a String representation. instance Show AvatarGridSide where-  show x = (showGrid . unAvatarGridSide) x+  show = showGrid . unAvatarGridSide  -- | Converts a grid of boolean values into a String representation. --@@ -285,7 +285,7 @@ -- y-axis. mirrorGrid :: AvatarGridSide -> AvatarGrid mirrorGrid side = AvatarGrid $ map mirror $ unAvatarGridSide side-  where mirror l = l ++ (reverse l)+  where mirror l = l ++ reverse l  -- | Generates the right side of an AvatarGrid using the given seed. generateAvatarGridSide :: Seed -> AvatarGridSide@@ -294,7 +294,7 @@ -- | Converts the given hexidecimal number String into a grid of boolean values. numToGrid :: String -> [[Bool]] numToGrid s = boolGrid-  where boolGrid = (map . map) convertToPixel $ (map . map) ord numGrid+  where boolGrid = (map . map) (convertToPixel . ord) numGrid         numGrid  = chunksOf 4 s         convertToPixel = (> ord '7')