Opps:
setPixel = State setPixel'

should be:
setPixel x y rgb = State $ setPixel' x y rgb

- Job

On Thu, Aug 20, 2009 at 1:05 PM, Job Vranish <jvranish@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, afterPixel])

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@yahoo.com> wrote:
Hi,
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]
        where
                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?

Regards,
Kashyap


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe