packages feed

UTFTConverter 0.1.0.0 → 0.1.0.1

raw patch · 7 files changed

+265/−191 lines, 7 filesdep +image-typedep ~base

Dependencies added: image-type

Dependency ranges changed: base

Files

README.md view
@@ -30,13 +30,14 @@   * If you specify a non-existing directory as target, it will be created   * The length of the array is NOT preceded by `0x`   * You can use the flags in any order you want+  * This tool will check the files via magic bytes  ## Binaries    * precompiled binary for Ubuntu distributions in `bin/UTFTConverter_u` (compiled on Linux Mint 17)-  * precompiled binary for Windows in `bin/UTFTConverter_w.exe` (compiled on Windows 7) (TODO)+  * precompiled binary for Windows in `bin/UTFTConverter_w.exe` (compiled on Windows 7) -## Installation:+## Installation via cabal:  **Step 1**: Install the Glasgow Haskell Compiler and `cabal` OR the Haskell packaging tool @@ -52,21 +53,29 @@  **Step 2**: When you have `ghc` and `cabal` OR the Haskell Platform installed: -#### If you want the library AND the binary (the easier way) (still to be uploaded on hackage):+#### If you want the library AND the binary (the easier way):   * run `cabal install UTFTConverter`   * the executable is now at `~/.cabal/bin/UTFTConverter`  #### If you want to build it by hand:-  * download the JuicyPixels library - `cabal install JuicyPixels`+  * download the JuicyPixels library - `cabal install JuicyPixels` | `stack install    * download the git repository - `git clone http://github.com/cirquit/UTFTConverter`   * run `make` and the binary is in the same directory OR-  * run `cabal install` and the binary is in `/dist/build/` and in your home directory under `~/.cabal/bin/UTFTConverter`+  * run `cabal install` and the binary is in `/dist/build/` and in your home directory under `~/.cabal/bin/UTFTConverter` OR+  * run `stack build && stack install` and the binary is somewhere in your `.stack-work/` ++## Installation via stack:++ * Install stack [Official guide](https://github.com/commercialhaskell/stack/blob/master/doc/GUIDE.md) / [My simplified guide](https://github.com/cirquit/ffp-lib)+ * open your shell and type `stack setup`+ * after that `stack install UTFTConverter`+ * look up the messages where your executable lies+ #### To do:    * maybe add resizing with a basic linear algorithm   * I'm planning to make a simple API that you can start locally which accepts any below defined formats and responses with the parsed `.raw` file. (another project)-  * add `stack` support  #### About: 
UTFTConverter.cabal view
@@ -1,84 +1,86 @@ name:                UTFTConverter category:            Graphics, Text-version:             0.1.0.0+version:             0.1.0.1 license:             MIT cabal-version:       >=1.10 license-file:        LICENSE author:              Alexander Isenko-maintainer:          Alexander Isenko <alex.isenko@googlemail.com>-homepage:            www.github.com/cirquit/UTFTConverter-bug-reports:         www.github.com/cirquit/UTFTConverter/issues+maintainer:          Alexander Isenko <alex.isenko@protonmail.com>+homepage:            http://github.com/cirquit/UTFTConverter+bug-reports:         http://github.com/cirquit/UTFTConverter/issues build-type:          Simple-tested-with:         GHC == 7.8.3 synopsis:            Processing popular picture formats into .c or .raw format in RGB565 description:-  __About:__+  /About:/   .   This package was created because I could not find a tool that can be used on UNIX systems to-  parse a picture into an array of RGB565 values and save them to a @.c@ or @.raw@ file. Both formats+  parse a picture into an array of 'RGB565' values and save them to a '.c' or '.raw' file. Both formats   are used by the <http://www.rinkydinkelectronics.com/library.php?id=51 UTFT library> to display pictures on to a TFT display.   .   This package includes, but not limited to, an executable which is made to be as identical as possible   to the corresponding tool that is also downloaded with the <http://www.rinkydinkelectronics.com/library.php?id=51 UTFT library>.   .-  __Usage:__   .-  >./UTFTConverter <filespec> /c|r [/o <path>] [/t AVR|ARM|PIC32]-  >-  ><filespec>:  File(s) to convert-  >parameters: /c            - Create output as .c array files-  >            /r            - Create output as .raw files-  >            /o <path>     - Set the output directory to <path>-  >            /t <platform> - Select target plaform-  >                            AVR   : Most Arduinos, Bobuion-  >                            ARM   : Arduino Due, Teensy, TI CC3200 LaunchPad-  >                            PIC32 : All chipKit boards-  >-  >You must specify either /c or /r. All other parameters are optional.-  >If /o is ommited the current directory will be used for output.-  >If /t is ommited the target platform will be set to AVR.'+  /Usage:/   .+  > ./UTFTConverter <filespec> /c|r [/o <path>] [/t AVR|ARM|PIC32]+  > +  > <filespec>:  File(s) to convert+  > parameters: /c            - Create output as .c array files+  >             /r            - Create output as .raw files+  >             /o <path>     - Set the output directory to <path>+  >             /t <platform> - Select target plaform+  >                             AVR   : Most Arduinos, Bobuion+  >                             ARM   : Arduino Due, Teensy, TI CC3200 LaunchPad+  >                             PIC32 : All chipKit boards+  > +  > You must specify either /c or /r. All other parameters are optional.+  > If /o is ommited the current directory will be used for output.+  > If /t is ommited the target platform will be set to AVR.'   .-  __Supported formats:__   .+  /Supported formats:/+  .+  The binary tests if the pictures are encoded correctly via magic bytes using <http://hackage.haskell.org/package/image-type ImageType>. If the extention is wrong, but the encoding is correct, it will still try to convert the picture.+  .   The exported library is using <http://hackage.haskell.org/package/JuicyPixels JuicyPixels> to convert incoming   .-  * @.gif@+  * '.gif'   .-  * @.png@+  * '.png'   .-  * @.jpg \/\ .jpe \/\ .jpeg@+  * '.jpg' \/\ '.jpe' \/\ '.jpeg'   .-  * @.bmp@+  * '.bmp'   .-  * @.tga@+  * '.tga'   .-  and translates every pixel to a @RGB565@ format, which is a 4 digit hex number.+  and translates every pixel to a 'RGB565' format, which is a 4 digit hex number.   .-  __Library:__   .-  The only really reusable library is the @Format.RGB565@.+  /Library:/+  .+  The only really reusable library is the 'Format.RGB565'.   It support the conversion from   .-  * @RGB@ to @RGB565@ as @(Word8, Word8, Word8) -> Int@-  * @Int@ to @Hex@ as @Int -> String@+  * 'RGB' to 'RGB565' as ('Word8', 'Word8', 'Word8') -> 'Int'   .-  __Example usage:__+  * 'Int' to 'Hex' as 'Int' -> 'String'   .-  >>> toRGB565 (0, 0, 255)-  31--  >>> toRGB565Hex (0, 0, 255)-  "001F"--  >>> toHex 100-  64--  >>> to4Hex 100-  "0064"--  >>> to6Hex 100-  "000064"+  .+  /Example usage:/+  .+  > >>> toRGB565 (0, 0, 255)+  > 31+  .+  > >>> toRGB565Hex (0, 0, 255)+  > "001F"+  .+  > >>> toHex 100+  > 64+  .+  > >>> toNHex 6 100+  > "0064"  extra-source-files:   Makefile@@ -95,10 +97,11 @@  library   build-depends:-      base        >=4.7  && <4.8  ,-      filepath    >=1.3  && <1.4  ,+      base        >=4.7  && <4.9  ,+      filepath    >=1.3  && <1.5  ,       directory   >=1.2  && <1.3  ,-      time        >=1.4  && <1.5  ,+      time        >=1.4  && <1.6  ,+      image-type       >=0.1.0.0  ,       bytestring  >=0.10 && <0.11 ,       JuicyPixels >=3.2  && <3.3 @@ -123,10 +126,10 @@  executable UTFTConverter   build-depends:-    base             >=4.7  && <4.8  ,-    filepath         >=1.3  && <1.4  ,+    base             >=4.7  && <4.9  ,+    filepath         >=1.3  && <1.5  ,     directory        >=1.2  && <1.3  ,-    time             >=1.4  && <1.5  ,+    time             >=1.4  && <1.6  ,     bytestring       >=0.10 && <0.11 ,     JuicyPixels      >=3.2  && <3.3  ,     UTFTConverter    ==0.1.*@@ -147,10 +150,10 @@  test-suite lib-tests   build-depends:-    base             >=4.7  && <4.8  ,-    filepath         >=1.3  && <1.4  ,+    base             >=4.7  && <4.9  ,+    filepath         >=1.3  && <1.5  ,     directory        >=1.2  && <1.3  ,-    time             >=1.4  && <1.5  ,+    time             >=1.4  && <1.6  ,     bytestring       >=0.10 && <0.11 ,     JuicyPixels      >=3.2  && <3.3  ,     hspec            ==2.1.*         ,
main-src/Main.hs view
@@ -6,7 +6,7 @@ import System.Environment    (getArgs, getProgName) import System.Exit           (exitFailure) -import Format.Converter      (pictureToC, pictureToRaw)+import Format.Converter      (pictureToC, pictureToRaw, toMaybeFormat, Format(..)) import Format.C              (Platform(..))  type Args = [String]@@ -14,11 +14,11 @@ data FileType = C | Raw  data Option = Option- { outdir   :: FilePath- , platform :: Platform- , filetype :: Maybe FileType- , files    :: [FilePath]- }+  { outdir   :: FilePath+  , platform :: Platform+  , filetype :: Maybe FileType+  , files    :: [(Format, FilePath)]+  }   main :: IO ()@@ -78,41 +78,39 @@ -- files parser argsParser (fp           :xs) opt = do   exists <- doesFileExist fp-  case (exists, takeExtension fp) of-    (True, ".jpg")  -> argsParser xs (opt { files = fp : files opt})-    (True, ".jpeg") -> argsParser xs (opt { files = fp : files opt})-    (True, ".jpe")  -> argsParser xs (opt { files = fp : files opt})-    (True, ".bmp")  -> argsParser xs (opt { files = fp : files opt})-    (True, ".png")  -> argsParser xs (opt { files = fp : files opt})-    (True, ".gif")  -> argsParser xs (opt { files = fp : files opt})-    (True, ".tga")  -> argsParser xs (opt { files = fp : files opt})-    (True,      _)  -> putStrLn ("WARNING: This format is not supported ~ " ++ fp) >> argsParser xs opt-    (False,     _)  -> putStrLn ("WARNING: Unreconized flag ~ "    ++ fp) >> argsParser xs opt+  mext   <- toMaybeFormat fp+  case (exists, mext) of+    (True, Just ext) -> argsParser xs (opt { files = (ext, fp) : files opt })+    (True,  Nothing) -> putStrLn ("WARNING: This format is not supported ~ " ++ fp) >> argsParser xs opt+    (False,       _) -> putStrLn ("WARNING: Unreconized flag ~ "    ++ fp) >> argsParser xs opt  printOpt :: (FilePath, Platform, FileType) -> IO () printOpt (outdir', platform', C)   = do-  putStrLn $ "Converting to     : .c array file(s)"-  putStrLn $ "Target platform   : " ++ show platform'-  putStrLn $ "Output directory  : " ++ outdir'        ++ "\n"-  putStrLn   "Processing file(s):"+  putStrLn $ unlines [ "Converting to     : .c array file(s)"+                     , "Target platform   : " ++ show platform'+                     , "Output directory  : " ++ outdir'        ++ "\n"+                     , "Processing file(s):"+                     ] printOpt (outdir',        _, Raw) = do-  putStrLn $ "Converting to     : .raw file(s)"-  putStrLn $ "Output directory  : " ++ outdir'        ++ "\n"-  putStrLn   "Processing file(s):"+  putStrLn $ unlines [ "Converting to     : .raw file(s)"+                     , "Output directory  : " ++ outdir'        ++ "\n"+                     , "Processing file(s):"+                     ]  help :: IO () help = do   name <- getProgName-  putStrLn   "\nUsage:                                           "-  putStrLn $ "      " ++ name ++ " <filespec> /c|r [/o <path>] [/t AVR|ARM|PIC32]\n"-  putStrLn   "<filespec>:  File(s) to convert"-  putStrLn   "parameters: /c            - Create output as .c array files"-  putStrLn   "            /r            - Create output as .raw files"-  putStrLn   "            /o <path>     - Set the output directory to <path>\n"-  putStrLn   "            /t <platform> - Select target plaform"-  putStrLn   "                            AVR   : Most Arduinos, Bobuion"-  putStrLn   "                            ARM   : Arduino Due, Teensy, TI CC3200 LaunchPad"-  putStrLn   "                            PIC32 : All chipKit boards\n"-  putStrLn   "You must specify either /c or /r. All other parameters are optional."-  putStrLn   "If /o is ommited the current directory will be used for output."-  putStrLn   "If /t is ommited the target platform will be set to AVR."+  putStrLn $ unlines [ "\nUsage:                                           "+                     , "      " ++ name ++ " <filespec> /c|r [/o <path>] [/t AVR|ARM|PIC32]\n"+                     , "<filespec>:  File(s) to convert"+                     , "parameters: /c            - Create output as .c array files"+                     , "            /r            - Create output as .raw files"+                     , "            /o <path>     - Set the output directory to <path>\n"+                     , "            /t <platform> - Select target plaform"+                     , "                            AVR   : Most Arduinos, Bobuion"+                     , "                            ARM   : Arduino Due, Teensy, TI CC3200 LaunchPad"+                     , "                            PIC32 : All chipKit boards\n"+                     , "You must specify either /c or /r. All other parameters are optional."+                     , "If /o is ommited the current directory will be used for output."+                     , "If /t is ommited the target platform will be set to AVR."+                     ]
src/Format/C.hs view
@@ -11,7 +11,7 @@ module Format.C (toCFile, Platform(..)) where  import Data.Time        (UTCTime)-import Format.RGB565    (to4Hex)+import Format.RGB565    (toNHex)   -- | The Platform datatype has three constructors, for every supported architecture@@ -26,9 +26,9 @@ -- -- * @[String]@ are the hex strings -- * @(String, String)@ is the (filename, file extention)--- * @(Int, Int) is the (width, height)--- * UTCTime is the current time--- * Platform is the desired platform to convert to+-- * @(Int, Int)@ is the (width, height)+-- * @UTCTime@ is the current time+-- * @Platform@ is the desired platform to convert to -- -- The result is a the string which is the full c file with header + unsigned short array + comments --@@ -81,4 +81,4 @@ printHex hx = '0':'x': hx ++ ", "  printCom :: Int -> String-printCom n = ' ':' ':'/':'/':' ':'0':'x': to4Hex n ++ ' ':'(': show n ++ ") pixels\n"+printCom n = ' ':' ':'/':'/':' ':'0':'x': toNHex 4 n ++ ' ':'(': show n ++ ") pixels\n"
src/Format/Converter.hs view
@@ -16,18 +16,18 @@ -- * @.bmp@ -- * @.tga@ ----- If it's not any of those formats, an error gets thrown--- If there is an error while decoding the pictures it gets printed out+-- If it's not any of those formats, an error gets thrown and if there is an error while decoding the pictures it only gets printed out (it gets skipped)  ----------------------------------------------------------------------------- -module Format.Converter (pictureToRaw, pictureToC) where+module Format.Converter (pictureToRaw, pictureToC, toMaybeFormat, Format(..)) where  import qualified Data.ByteString as BS (readFile) import Data.ByteString.Lazy            (toStrict) import System.FilePath.Posix           (takeBaseName, (</>),                                         takeExtension, takeFileName) import Data.Time                       (getCurrentTime)+import Data.Char                       (toUpper)  import Codec.Picture.Types import Codec.Picture.Saving            (imageToBitmap)@@ -37,17 +37,94 @@ import Codec.Picture.Gif               (decodeGif) import Codec.Picture.Tga               (decodeTga) +import Codec.ImageType                 (getFileType)+ import Format.RGB565                   (toRGB565Hex) import Format.C                        (toCFile, Platform()) import Format.Raw                      (toRawFile) +-- | Currently supported picture formats (by JuicyPixels)+--+data Format = Jpeg+            | Bmp+            | Png+            | Gif+            | Tga++instance Show Format where+    show Jpeg = "jpeg"+    show Bmp  = "bmp"+    show Png  = "png"+    show Gif  = "gif"+    show Tga  = "tga"++instance Read Format where+    readsPrec _ e = do+        (s,r) <- lex e+        case map toUpper s of+            "JPEG" -> return (Jpeg, r)+            "JPG"  -> return (Jpeg, r)+            "JPE"  -> return (Jpeg, r)+            "GIF"  -> return (Gif, r)+            "BMP"  -> return (Bmp, r)+            "PNG"  -> return (Png, r)+            "TGA"  -> return (Tga, r)+            _      -> fail "Read Format: no parse"++-- | Checking if the format is supported via magic bytes+--   safe checking for everything unless __.tga__+--+--  __Possible errors:__+--  +--  * It will be problematic in the future if you try to read the file as .tga if it's not encoded as one+--+--  __Example usage:__+--+--  @+--  λ> toMaybeFormat "cat_01_bmp_120x120.bmp"+--  Just Bmp+--  λ> toMaybeFormat "cat_01_bmp_120x120.jpeg"+--  Just Jpeg+--  λ> toMaybeFormat "cat_01_bmp_120x120.jpe"+--  Just Jpeg+--  @++toMaybeFormat :: FilePath -> IO (Maybe Format)+toMaybeFormat fp = do+    mtp <- getFileType fp+    let ext = drop 1 $ takeExtension fp+        validFormats = map show [Jpeg, Bmp, Png, Gif, Tga]+    case (mtp, ext) of+      (Just "jpeg", _)+          | ext `elem` ["jpg", "jpeg", "jpe"] -> return $ Just Jpeg+      (Just tp, _)+          | tp `elem` validFormats, tp == ext -> return $ Just $ read tp+          | tp `elem` validFormats            -> do+                putStrLn $ "WARNING: File format is " ++ '.':tp ++ ", not " ++ '.':ext ++ " ~ " ++ fp+                return $ Just $ read fp+      (_, _)+          | "tga" <- ext                      -> return $ Just Tga+          | otherwise                         -> return Nothing+++formatToDynImg :: Format -> FilePath -> IO (Maybe DynamicImage)+formatToDynImg f fp = do+    case f of+        Jpeg -> jpgToDynImg fp+        Bmp  -> bmpToDynImg fp+        Png  -> pngToDynImg fp+        Gif  -> gifToDynImg fp+        Tga  -> tgaToDynImg fp+--      ft@_    -> error $ "Converter.hs: formatToDynImg:91 - Unsupported Format - " ++ show ft++ -- | pictureToRaw takes a picture, decodes it, parses every pixel to a 4 digit RGB565 hex and saves it to --   a file with the same name and a @.raw@ extention in the specified directory -- -- This function takes two arguments -- -- * first @FilePath@ is the directory to save the file to--- * second @FilePath@ is the filepath to the picture+-- * second @(Format, FilePath)@ is the format and filepath of the picture -- -- __Possible errors:__ --@@ -66,22 +143,12 @@ -- -- @ -- λ> dir <- getCurrentDirectory--- λ> pictureToRaw dir "cat_01_bmp_120x120.bmp"+-- λ> pictureToRaw dir (Bmp, "cat_01_bmp_120x120.bmp") -- cat_01_bmp_120x120.bmp --> cat_01_bmp_120x120.raw -- @ -pictureToRaw :: FilePath -> FilePath -> IO ()-pictureToRaw saveTo fp = do-  case takeExtension fp of-    (".jpg")  -> jpgToDynImg fp >>= dynimgToRaw saveTo fp-    (".jpeg") -> jpgToDynImg fp >>= dynimgToRaw saveTo fp-    (".jpe")  -> jpgToDynImg fp >>= dynimgToRaw saveTo fp-    (".bmp")  -> bmpToDynImg fp >>= dynimgToRaw saveTo fp-    (".png")  -> pngToDynImg fp >>= dynimgToRaw saveTo fp-    (".gif")  -> gifToDynImg fp >>= dynimgToRaw saveTo fp-    (".tga")  -> tgaToDynImg fp >>= dynimgToRaw saveTo fp-    (_)       -> error "Argument filter let through some unsupported types"-+pictureToRaw :: FilePath -> (Format, FilePath) -> IO ()+pictureToRaw saveTo (format,fp) = formatToDynImg format fp >>= dynimgToRaw saveTo fp  -- | pictureToC takes a picture, decodes it, parses every pixel to a 4 digit RGB565 hex, adds the header --   based on the desired platform and saves it to a file with the same name and a @.c@ extention in the specified@@ -91,7 +158,7 @@ -- -- * @Platform@ is the desired platform to convert to -- * first @FilePath@ is the directory to save the file to--- * second @FilePath@ is the filepath to the picture+-- * second @(Format, FilePath)@ is the format and filepath of the picture -- -- __Possible errors:__ --@@ -110,21 +177,12 @@ -- -- @ -- λ> dir <- getCurrentDirectory--- λ> pictureToC AVR dir "cat_01_bmp_120x120.bmp"+-- λ> pictureToC AVR dir (Bmp, "cat_01_bmp_120x120.bmp") -- cat_01_bmp_120x120.bmp --> cat_01_bmp_120x120.c -- @ -pictureToC :: Platform -> FilePath -> FilePath -> IO ()-pictureToC platform saveTo fp = do-  case takeExtension fp of-    (".jpg")  -> jpgToDynImg fp >>= dynimgToC platform saveTo fp-    (".jpeg") -> jpgToDynImg fp >>= dynimgToC platform saveTo fp-    (".jpe")  -> jpgToDynImg fp >>= dynimgToC platform saveTo fp-    (".bmp")  -> bmpToDynImg fp >>= dynimgToC platform saveTo fp-    (".png")  -> pngToDynImg fp >>= dynimgToC platform saveTo fp-    (".gif")  -> gifToDynImg fp >>= dynimgToC platform saveTo fp-    (".tga")  -> tgaToDynImg fp >>= dynimgToC platform saveTo fp-    (_)       -> error "Argument filter let through some unsupported types"+pictureToC :: Platform -> FilePath -> (Format, FilePath) -> IO ()+pictureToC platform saveTo (format,fp) = formatToDynImg format fp >>= dynimgToC platform saveTo fp  jpgToDynImg :: FilePath -> IO (Maybe DynamicImage) jpgToDynImg fp = do
src/Format/RGB565.hs view
@@ -9,10 +9,12 @@ -- @Format.RGB565@ exports the functions to convert from a RGB value to RGB565 and the needed hex conversions -- ------------------------------------------------------------------------------module Format.RGB565 (toRGB565, toRGB565Hex, to6Hex, to4Hex, toHex) where+module Format.RGB565 (toRGB565, toRGB565Hex, toNHex, to6Hex, to4Hex, toHex) where  import Data.Bits (shiftL, shiftR, (.|.)) import Data.Word (Word8())+import Numeric   (showHex)+import Data.Char (toUpper)   -- | toRGB565Hex takes a RGB value and converts it into a RGB565 encoded 4 digit hex String@@ -25,7 +27,7 @@ -- @  toRGB565Hex :: (Word8, Word8, Word8) -> String-toRGB565Hex rgb = to4Hex (toRGB565 rgb)+toRGB565Hex rgb = toNHex 4 (toRGB565 rgb)  -- | toRGB565 takes a RGB value and converts it into a RGB565 encoded Int --@@ -45,70 +47,67 @@ toInt :: Word8 -> Int toInt = fromIntegral --- | toHex takes an Int and converts it into a hex String+-- | toHex takes an unsigned Int and converts it into a hex String -- -- __Example usage:__ -- -- @ -- λ> toHex 255--- \"F8\"+-- \"FF\" -- @ toHex :: Int -> String-toHex = go ""-  where go !acc x =-          case quotRem x 16 of-            (0,r) ->     hex r : acc-            (q,r) -> go (hex r : acc) q+toHex = map toUpper . flip showHex "" --- | to4Hex takes an Int and converts it to a hex String and adds zeros until four digits are filled+-- | toNHex takes the desired stringlength __n__ and an unsigned Int and converts it to a hex String and adds zeros until __n__ digits are filled -- -- __Example usage:__ -- -- @+-- λ> toNHex 4 255+-- "00FF"+--+-- λ> toNHex 6 255+-- "0000FF"+-- @+toNHex :: Int -> Int -> String+toNHex n x = map toUpper $ go hx+  where hx = toHex x+        go :: String -> String+        go !str+          | length str < n = go ('0':str)+          | otherwise      = str+++-- | to4Hex takes an unsigned Int and converts it to a hex String and adds zeros until four digits are filled+--+-- __Example usage:__+--+-- @ -- λ> to4Hex 255--- "00F8"+-- "00FF" -- @+{-# DEPRECATED to4Hex "Use toNHex 4 instead" #-} to4Hex :: Int -> String-to4Hex x = go hx+to4Hex x = map toUpper $ go hx   where hx = toHex x         go :: String -> String         go !str-          | length str < 4 = go ('0':str)+          | length str < 6 = go ('0':str)           | otherwise      = str --- | to6Hex takes an Int and converts it to a hex String and adds zeros until six digits are filled+-- | to4Hex takes an unsigned Int and converts it to a hex String and adds zeros until six digits are filled -- -- __Example usage:__ -- -- @--- λ> to4Hex 255--- "0000F8"+-- λ> to6Hex 255+-- "0000FF" -- @+{-# DEPRECATED to6Hex "Use toNHex 6 instead" #-} to6Hex :: Int -> String-to6Hex x = go hx+to6Hex x = map toUpper $ go hx   where hx = toHex x         go :: String -> String         go !str           | length str < 6 = go ('0':str)           | otherwise      = str----hex :: Int -> Char-hex 0  = '0'-hex 1  = '1'-hex 2  = '2'-hex 3  = '3'-hex 4  = '4'-hex 5  = '5'-hex 6  = '6'-hex 7  = '7'-hex 8  = '8'-hex 9  = '9'-hex 10 = 'A'-hex 11 = 'B'-hex 12 = 'C'-hex 13 = 'D'-hex 14 = 'E'-hex 15 = 'F'-hex x  = error $ "Exceeded bounds of 'hex' - " ++ show x
tests/Tests.hs view
@@ -1,12 +1,13 @@ module Main where -import Format.RGB565                   (toHex, to4Hex, toRGB565, toRGB565Hex)-import Format.Converter                (pictureToRaw)+import Format.RGB565                   (toHex, toNHex, toRGB565, toRGB565Hex)+import Format.Converter                (pictureToRaw, toMaybeFormat, Format()) import Test.Hspec import System.Directory                (getCurrentDirectory, doesDirectoryExist,                                         createDirectory, getDirectoryContents,                                         removeDirectoryRecursive) import System.FilePath.Posix           ((</>))+import Data.Maybe                      (fromJust) import Data.List                       (foldl')  main :: IO ()@@ -33,19 +34,19 @@           it "toHex should be 10000" $ do             toHex 65536 `shouldBe` "10000" -        describe "to4Hex" $ do-          it "to4Hex 0 should be 0000" $ do-            to4Hex 0     `shouldBe` "0000"-          it "to4Hex 12 should be 000C" $ do-            to4Hex 12    `shouldBe` "000C"-          it "to4Hex 198 should be 00C6" $ do-            to4Hex 198   `shouldBe` "00C6"-          it "to4Hex 122 should be 007A" $ do-            to4Hex 122   `shouldBe` "007A"-          it "to4Hex 255 should be 00FF" $ do-            to4Hex 255   `shouldBe` "00FF"-          it "to4Hex 65535 should be FFFF" $ do-            to4Hex 65535 `shouldBe` "FFFF"+        describe "toNHex" $ do+          it "toNHex 4 0 should be 0000" $ do+            toNHex 4 0     `shouldBe` "0000"+          it "toNHex 4 12 should be 000C" $ do+            toNHex 4 12    `shouldBe` "000C"+          it "toNHex 4 198 should be 00C6" $ do+            toNHex 4 198   `shouldBe` "00C6"+          it "toNHex 4 122 should be 007A" $ do+            toNHex 4 122   `shouldBe` "007A"+          it "toNHex 4 255 should be 00FF" $ do+            toNHex 4 255   `shouldBe` "00FF"+          it "toNHex 4 65535 should be FFFF" $ do+            toNHex 4 65535 `shouldBe` "FFFF"          describe "toRGB565" $ do           it "toRGB565 (255, 255, 255) should be 65535" $ do@@ -84,7 +85,7 @@           length (dir1 ++ dir2 ++ dir3) `shouldBe` 15         it "cat_01 pics should be all converted to almost the same .raw-files (>99% similarity)" $ do           createDirectory "tmp"-          pics <- getExamplePicsPath dir ("tests" </> "examples" </> "cat_01")+          pics <- getExampleFormatPicsPath dir ("tests" </> "examples" </> "cat_01")           mapM_ (pictureToRaw (dir </> "tmp")) pics           rawfps <- getExamplePicsPath dir "tmp"           [p1, p2, p3, p4, p5] <- mapM readFile rawfps@@ -100,7 +101,7 @@           ((r1 + r2 + r3 + r4) / 4) > 98 `shouldBe` True         it "cat_02 pics should be all converted to almost the same .raw-files (>99% similarity)" $ do           createDirectory "tmp"-          pics <- getExamplePicsPath dir ("tests" </> "examples" </> "cat_02")+          pics <- getExampleFormatPicsPath dir ("tests" </> "examples" </> "cat_02")           mapM_ (pictureToRaw (dir </> "tmp")) pics           rawfps <- getExamplePicsPath dir "tmp"           [p1, p2, p3, p4, p5] <- mapM readFile rawfps@@ -116,7 +117,7 @@           ((r1 + r2 + r3 + r4) / 4) > 98 `shouldBe` True         it "cat_03 pics should be all converted to almost the same .raw-files (>99% similarity)" $ do           createDirectory "tmp"-          pics <- getExamplePicsPath dir ("tests" </> "examples" </> "cat_03")+          pics <- getExampleFormatPicsPath dir ("tests" </> "examples" </> "cat_03")           mapM_ (pictureToRaw (dir </> "tmp")) pics           rawfps <- getExamplePicsPath dir "tmp"           [p1, p2, p3, p4, p5] <- mapM readFile rawfps@@ -131,12 +132,18 @@           removeDirectoryRecursive (dir </> "tmp")           ((r1 + r2 + r3 + r4) / 4) > 98 `shouldBe` True - getExamplePicsPath :: FilePath -> FilePath -> IO [FilePath] getExamplePicsPath curdir picdir = do   content <- getDirectoryContents (curdir </> picdir)   let picnames = filter (`notElem` [".", ".."]) content   return $ map (\x -> curdir </> picdir </> x) picnames++getExampleFormatPicsPath :: FilePath -> FilePath -> IO [(Format, FilePath)]+getExampleFormatPicsPath curdir picdir = do+  content <- getDirectoryContents (curdir </> picdir)+  let picnames = filter (`notElem` [".", ".."]) content+      picpaths = map (\x -> curdir </> picdir </> x) picnames+  flip zip picpaths . map fromJust <$> mapM toMaybeFormat picpaths  picSimilarity :: String -> String -> Double picSimilarity p1 p2 =