[Haskell-cafe] Right way to implement setPixel function
ck_kashyap at yahoo.com
Fri Aug 21 13:33:15 EDT 2009
thank you very much Job.
On Thu Aug 20th, 2009 1:13 PM EDT Job Vranish wrote:
>setPixel = State setPixel'
>setPixel x y rgb = State $ setPixel' x y rgb
>On Thu, Aug 20, 2009 at 1:05 PM, Job Vranish <jvranish at gmail.com> wrote:
>> Your setPixel function is almost ready to work in a State monad
>> If you modify your setPixel function slightly like so:
>> setPixel' :: Int -> Int -> Color -> B.ByteString -> ((), B.ByteString)
>> setPixel' x y (r,g,b) image = ((), B.concat [beforePixel, pixel,
>> and then wrap it in the State monad constructor:
>> setPixel = State setPixel'
>> then you can do
>> drawPixels = do
>> setPixel 5 10 (200, 0, 0)
>> setPixel 20 1 (0, 200, 0)
>> setPixel 90 2 (0, 0, 200)
>> modifiedImage = execState drawPixels originalImage
>> See! you were already using a monad and didn't even know it! :D
>> Performance wise, B.concat is O(n), which is very not good for your
>> purpose. It copies the whole string and the optimizer won't be able to
>> magically make it go away. For something that works in O(1), you will have
>> to use something like STArrays instead of bytestrings.
>> - Job
>> On Thu, Aug 20, 2009 at 2:32 AM, CK Kashyap <ck_kashyap at yahoo.com> wrote:
>>> I had posted a note on line drawing algo with Haskell some time back. Now,
>>> I am trying to write a PNM image.
>>> import qualified Data.ByteString as B
>>> width = 256
>>> height = 256
>>> bytesInImage = width * height * 3
>>> blankImage = B.pack $ take bytesInImage (repeat 0)
>>> type Color = (Int,Int,Int)
>>> setPixel :: B.ByteString -> Int -> Int -> Color -> B.ByteString
>>> setPixel image x y (r,g,b) = B.concat [beforePixel, pixel, afterPixel]
>>> beforePixel = B.take before image
>>> afterPixel = B.drop (before+3) image
>>> pixel=B.pack [(fromIntegral r),(fromIntegral
>>> g),(fromIntegral b)]
>>> -- number of bytes before the 3 bytes of
>>> -- the pixel at x y
>>> before = (y * width * 3) + (x * 3) - 3
>>> main = do
>>> putStrLn "P6"
>>> putStrLn ( (show width) ++ " " ++ (show height) )
>>> putStrLn "255"
>>> -- Set a red pixel at 100 100
>>> B.putStr (setPixel blankImage 100 100 (255,0,0))
>>> Can I please have some review comments on the code above? Would recreating
>>> the entire ByteString for each setPixel be an overhead?
>>> Also, I am barely beginning to grasp the Monad concept....I was wondering
>>> if there could be a monadic style of implementation of this - that could
>>> potentially have a series of setPixels inside a do block?
>>> Haskell-Cafe mailing list
>>> Haskell-Cafe at haskell.org
More information about the Haskell-Cafe