Created
December 13, 2021 20:37
-
-
Save fabiomolinar/301d7ea6628d4687203bf5ffa450afa2 to your computer and use it in GitHub Desktop.
First version of my Haskell code which I used to create an image with an array of colorful squares.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-| | |
Module : Degrade | |
Description : Creates an image with multiple squares of different colors. | |
Copyright : (c) Fabio Thomaz MOlinar, 2021 | |
Maintainer : fabiomolinar@gmail.com | |
Stability : experimental | |
This was my first attempt at creating a module that would be able to create an | |
image with multiple squares of different colors. Although it works, the efficiency | |
is __TERRIBLE__. | |
By profiling the code, I found out that a lot of time was spent at the call which | |
searches a multidimensional list by index: | |
> defaultColor = c!!(j - 1)!!(i - 1) | |
-} | |
module Squares.Degrade where | |
import Graphics.Image | |
-- |Returns a white canvas with a certain width and height | |
makeCanvas :: Int -- ^ Width | |
-> Int -- ^ Height | |
-> [[Pixel RGB Double]] | |
makeCanvas w h = [[PixelRGB 255 255 255 | _ <- [1..w]] | _ <- [1..h]] | |
-- |Ads a red square to a given position on a canvas | |
addSquareToCanvas :: [[Pixel RGB Double]] -- ^ The canvas | |
-> Int -- ^ X position | |
-> Int -- ^ Y position | |
-> Int -- ^ Width | |
-> Int -- ^ Height | |
-> Pixel RGB Double -- ^ Color | |
-> [[Pixel RGB Double]] | |
addSquareToCanvas c x y w h rgb = [[selectedColor i j | i <- [1..canvasWidth]] | j <- [1..canvasHeight]] | |
where | |
canvasWidth = getCanvasWidth c | |
canvasHeight = getCanvasHeight c | |
selectedColor i j = | |
if inRange i j | |
then rgb | |
else defaultColor | |
where | |
defaultColor = c!!(j - 1)!!(i - 1) | |
inRange i j = | |
i >= x && | |
i <= x + w - 1 && | |
j >= y && | |
j <= y + h - 1 | |
getCanvasWidth :: [[Pixel RGB Double]] -> Int | |
getCanvasWidth c = length $ head c | |
getCanvasHeight :: [[Pixel RGB Double]] -> Int | |
getCanvasHeight = length | |
-- | Since color functions below use Double precision, need to recal each value will range from 0.0 to 1.0 | |
redColor :: [[Pixel RGB Double]] -- ^ Canvas | |
-> Int -- ^ X | |
-> Int -- ^ Y | |
-> Pixel RGB Double | |
redColor c x y = PixelRGB 1.0 0.0 0.0 | |
linearDegradeColor :: [[Pixel RGB Double]] -- ^ Canvas | |
-> Int -- ^ X | |
-> Int -- ^ Y | |
-> Pixel RGB Double | |
linearDegradeColor c x y = PixelRGB (fromIntegral x) (fromIntegral y) 0.0 / fromIntegral (max (getCanvasWidth c) (getCanvasHeight c)) | |
addSquareXTimesHorizontally :: Int -- ^ Number of times | |
-> Int -- ^ X0 | |
-> Int -- ^ Y0 | |
-> Int -- ^ Spacing | |
-> Int -- ^ Square width | |
-> Int -- ^ Square height | |
-> ([[Pixel RGB Double]] -> Int -> Int -> Pixel RGB Double) -- ^ Coloring function | |
-> [[Pixel RGB Double]] -- ^ Canvas | |
-> [[Pixel RGB Double]] | |
addSquareXTimesHorizontally 0 x0 y0 s w h rgb c = c | |
addSquareXTimesHorizontally n x0 y0 s w h rgb c = | |
addSquareXTimesHorizontally (n - 1) x0 y0 s w h rgb $ addSquareToCanvas | |
c | |
(x0 + (w + s) * (n - 1)) | |
y0 | |
w | |
h | |
color | |
where | |
color = rgb c (x0 + (w + s) * (n - 1)) y0 | |
addSquareXY :: Int -- ^ Squares in Y | |
-> Int -- ^ Squares in X | |
-> Int -- ^ Margin | |
-> Int -- ^ Spacing | |
-> Int -- ^ Square width | |
-> Int -- ^ Square height | |
-> ([[Pixel RGB Double]] -> Int -> Int -> Pixel RGB Double) -- ^ Coloring function | |
-> [[Pixel RGB Double]] -- ^ Canvas | |
-> [[Pixel RGB Double]] | |
addSquareXY 0 x m s w h rgb c = c | |
addSquareXY y x m s w h rgb c = | |
addSquareXY (y - 1) x m s w h rgb $ addSquareXTimesHorizontally | |
x | |
(m + 1) | |
(m + 1 + (h + s) * (y - 1)) | |
s | |
w | |
h | |
rgb | |
c | |
-- | Code used for testing | |
makeThreeSquares :: Int -- ^ Margin | |
-> Int -- ^ Spacing | |
-> Int -- ^ Width | |
-> Int -- ^ Height | |
-> [[Pixel RGB Double]] | |
makeThreeSquares m s w h = | |
let | |
canvas = makeCanvas (2*m+2*s+3*w) (2*m+h) | |
in addSquareXTimesHorizontally 3 (m + 1) (m + 1) s w h redColor canvas | |
-- |Makes a red square of a given width and height | |
makeRedSquare :: Int -- ^ Width | |
-> Int -- ^ Height | |
-> [[Pixel RGB Double]] | |
makeRedSquare w h = [[PixelRGB 255 0 0 | _ <- [1..w]] | _ <- [1..h]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment