binary-file-0.15.25: examples/readBitmap.hs
{-# LANGUAGE ScopedTypeVariables #-}
import System.Environment
import Control.Applicative
import BitmapCore
import Data.List
import Data.Maybe
main :: IO ()
main = do
[inf, outf] <- getArgs
Right (bmp :: Bitmap, "") <- fromBinary () <$> readBinaryFile inf
putStrLn $ take 5000 (show bmp) ++ "..."
let img = bmpToImage bmp
bmp' = imageToBMP img
Right bin = toBinary () bmp'
writeBinaryFile outf bin
type Image = [[RGB8]]
data RGB8 = RGB8 Int Int Int deriving (Show, Eq, Ord)
border, border2 :: Image
border = take 100 $ cycle
[replicate 100 $ RGB8 0 0 0, replicate 100 $ RGB8 255 255 255]
border2 = take 100 $ cycle [
replicate 100 $ RGB8 0 0 0, replicate 100 $ RGB8 255 255 255,
replicate 100 $ RGB8 255 0 0, replicate 100 $ RGB8 0 0 255
]
rgb24ToRGB8 :: RGB24 -> RGB8
rgb24ToRGB8 (RGB24 r g b) = RGB8 r g b
rgb32ToRGB8 :: RGB32 -> RGB8
rgb32ToRGB8 (RGB32 r g b) = RGB8 r g b
rgb8ToRGB32 :: RGB8 -> RGB32
rgb8ToRGB32 (RGB8 r g b) = RGB32 r g b
rgb8ToRGB24 :: RGB8 -> RGB24
rgb8ToRGB24 (RGB8 r g b) = RGB24 r g b
linesToImage :: [RGB32] -> [Line] -> Image
linesToImage plt = reverse . map (pixelsToImage plt . line)
pixelsToImage :: [RGB32] -> Pixels -> [RGB8]
pixelsToImage _ (Colors24 cs) = map rgb24ToRGB8 cs
pixelsToImage _ (Colors32 cs) = map rgb32ToRGB8 cs
pixelsToImage plt (Indices is) = map rgb32ToRGB8 $ map (plt !!) is
bmpToImage :: Bitmap -> Image
bmpToImage = linesToImage <$> colors <*> image
getImage :: [RGB32] -> Image -> [Line]
getImage plt = map (Line . imageToPixels plt)
imageToPixels :: [RGB32] -> [RGB8] -> Pixels
imageToPixels plt ln
| notBigger 256 plt =
Indices $ map (fromJust . flip findIndex plt . (==) . rgb8ToRGB32) ln
| otherwise = Colors24 $ map rgb8ToRGB24 ln
getMandrill :: IO Image
getMandrill = do
Right (bmp, "") <- fromBinary () <$> readBinaryFile "tmp/Mandrill.bmp"
return $ bmpToImage bmp
getLady :: IO Image
getLady = do
Right (bmp, "") <- fromBinary () <$> readBinaryFile "tmp/test.bmp"
return $ bmpToImage bmp
imageToBMP :: Image -> Bitmap
imageToBMP img_ = Bitmap {
fileSize = ofst + isize,
offset = ofst,
width = length $ head img,
height = length img,
bits_per_pixel = getbpp plt,
compression = 0,
image_size = getISize plt img,
resolutionH = 0,
resolutionV = 0,
color_num = cnum,
important_colors_num = 0,
colors = if notBigger 256 plt then plt else [],
image = getImage plt img
}
where
plt = getColors img
cnum = if notBigger 256 plt then length plt else 0
ofst = getOffset plt
isize = getISize plt img
img = reverse img_
getColors :: Image -> [RGB32]
getColors = map (rgb8ToRGB32 . head) . group . sort . concat
notBigger :: Int -> [a] -> Bool
notBigger _ [] = True
notBigger 0 _ = False
notBigger n (x : xs) = notBigger (n - 1) xs
getbpp :: [RGB32] -> Int
getbpp cs
| notBigger 2 cs = 1
| notBigger 16 cs = 4
| notBigger 256 cs = 8
| otherwise = 24
getISize :: [RGB32] -> Image -> Int
getISize plt img = addPadd (bpp * w) `div` 8 * h
where
bpp = getbpp plt
w = length $ head img
h = length img
addPadd x = x + paddBits x
getOffset :: [RGB32] -> Int
getOffset plt
| notBigger 256 plt = length plt * 4 + 54
| otherwise = 54
strsToImage :: [String] -> Image
strsToImage = map strToRGBs
strToRGBs :: String -> [RGB8]
strToRGBs = map $ fromJust . flip lookup [
('*', RGB8 255 0 0),
('#', RGB8 0 0 0),
('.', RGB8 255 255 255)
]
strsToBin :: (Monad m, Applicative m) => [String] -> m String
strsToBin = toBinary () . imageToBMP . strsToImage
writeStrPic :: FilePath -> [String] -> IO ()
writeStrPic fp strs = writeBinaryFile fp =<< strsToBin strs
flipH = reverse
flipV = map reverse
scale img n = concatMap (replicate n . concatMap (replicate n)) img
above = (++)
beside = zipWith (++)
rotate = flipH . flipV
nega = map $ map $ \p -> case p of { '#' -> '.'; '*' -> '.'; '.' -> '*' }
superimpose = zipWith (zipWith combine)
combine topCh botCh
| topCh == '#' = '#'
| topCh == '*' = '*'
| botCh == '#' = '#'
| botCh == '*' = '*'
| otherwise = '.'
sampleImg :: [String]
sampleImg = [
"******************************************************",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*........*******************.........................*",
"*.........*****************..........................*",
"*..........***************...........................*",
"*...........*************............................*",
"*............***********.............................*",
"*.............*********..............................*",
"*..............*******...............................*",
"*...............*****................................*",
"*................***.................................*",
"*.................*..................................*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*............**......................................*",
"*............**......................................*",
"*............**......................................*",
"*............**......................................*",
"*............**......................................*",
"*............**......................................*",
"*............**......................................*",
"*............**......................................*",
"*............**......................................*",
"*............**......................................*",
"*............**......................................*",
"*............**....................***...............*",
"*............**...................*****..............*",
"*............**...................*****..............*",
"*.................................*****..............*",
"*..................................***...............*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"*....................................................*",
"******************************************************"
]
horse :: [String]
horse = [
".......##...",
".....##..#..",
"...##.....#.",
"..#.......#.",
"..#...#...#.",
"..#...###.#.",
".#....#..##.",
"..#...#..##.",
"...#...#....",
"....#...#...",
".....#..#...",
"......#.#...",
".......##..."
]
yo :: [String]
yo = [
"................",
"................",
".......##.......",
".......##.......",
".......##.......",
".......#####....",
".......#####....",
".......##.......",
".......##.......",
".......##.......",
".....#######....",
"....#########...",
"...##..##..##...",
"...######.......",
"....####........",
"................"
]
shi :: [String]
shi = [
".............",
".............",
"...##........",
"...##........",
"...##........",
"...##........",
"...##........",
"...##........",
"...##........",
"...##........",
"...##....##..",
"...##....##..",
"....#######..",
".....####....",
".............",
"............."
]
ku :: [String]
ku = [
"...............",
"...............",
".......###.....",
"......###......",
".....###.......",
"....###........",
"...###.........",
"..###..........",
"..###..........",
"...###.........",
"....###........",
".....###.......",
"......###......",
".......###.....",
"...............",
"..............."
]
ni :: [String]
ni = [
"................",
"................",
"..##............",
"..##...#####....",
"..##..#######...",
"..##............",
"..##............",
"..##............",
"..##............",
"..##............",
"..##..#######...",
"..##...#####....",
"...##...........",
"...##...........",
"................",
"................"
]
margeH :: [RGB8] -> [RGB8]
margeH [] = []
margeH [rgb] = [rgb]
margeH (RGB8 r1 g1 b1 : RGB8 r2 g2 b2 : rest) =
RGB8 (average r1 r2) (average g1 g2) (average b1 b2) : margeH rest
average x y = (x + y) `div` 2
averageRGB8 (RGB8 r1 g1 b1) (RGB8 r2 g2 b2) =
RGB8 (average r1 r2) (average g1 g2) (average b1 b2)
scaleDownH :: Image -> Image
scaleDownH = map margeH
scaleDownV :: Image -> Image
scaleDownV [] = []
scaleDownV [l] = [l]
scaleDownV (l1 : l2 : rest) = zipWith averageRGB8 l1 l2 : scaleDownV rest
scaleDown :: Image -> Image
scaleDown = scaleDownV . scaleDownH
getLena64 = scaleDown <$> scaleDown <$> scaleDown <$> getLady
getMandrill64 = scaleDown <$> scaleDown <$> scaleDown <$> getMandrill
writeImage :: FilePath -> Image -> IO ()
writeImage fp img = writeBinaryFile fp =<< toBinary () (imageToBMP img)
mirrorV img = img `beside` flipV img
mirrorH img = img `above` flipH img
mirror = mirrorV . mirrorH
scalePattern :: Image -> Image
scalePattern img =
img' `beside` img' `above` img `beside` (img' `above` img' `above` img')
where
img' = scaleDown img
gradation :: Image
gradation =
replicate 5 (map (\x -> RGB8 x x x) $ [0, 2 .. 255]) ++
replicate 5 (map (\x -> RGB8 x 0 0) $ [0, 2 .. 255]) ++
replicate 5 (map (\x -> RGB8 0 x 0) $ [0, 2 .. 255]) ++
replicate 5 (map (\x -> RGB8 0 0 x) $ [0, 2 .. 255])