Your setPixel function is almost ready to work in a State monad<br>If you modify your setPixel function slightly like so:<br><br>setPixel' :: Int -> Int -> Color -> B.ByteString -> ((), B.ByteString)<br>setPixel' x y (r,g,b) image = ((), B.concat [beforePixel, pixel, afterPixel])<br>
<br>and then wrap it in the State monad constructor:<br><br>setPixel = State setPixel'<br><br>then you can do <br><br>drawPixels = do<br> setPixel 5 10 (200, 0, 0)<br> setPixel 20 1 (0, 200, 0)<br> setPixel 90 2 (0, 0, 200)<br>
<br>modifiedImage = execState drawPixels originalImage<br><br>See! you were already using a monad and didn't even know it! :D<br><br>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.<br>
<br>- Job<br><br><br><br><div class="gmail_quote">On Thu, Aug 20, 2009 at 2:32 AM, CK Kashyap <span dir="ltr"><<a href="mailto:ck_kashyap@yahoo.com">ck_kashyap@yahoo.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div><div style="font-family: times new roman,new york,times,serif; font-size: 12pt;"><div>Hi,<br>I had posted a note on line drawing algo with Haskell some time back. Now, I am trying to write a PNM image.<br><br>import qualified Data.ByteString as B<br>
<br>width = 256<br>height = 256<br>bytesInImage = width * height * 3<br>blankImage = B.pack $ take bytesInImage (repeat 0)<br><br>type Color = (Int,Int,Int)<br>setPixel :: B.ByteString -> Int -> Int -> Color -> B.ByteString<br>
setPixel image x y (r,g,b) = B.concat [beforePixel, pixel, afterPixel]<br> where<br> beforePixel = B.take before image<br> afterPixel = B.drop (before+3)
image<br> pixel=B.pack [(fromIntegral r),(fromIntegral g),(fromIntegral b)]<br> -- number of bytes before the 3 bytes of<br> -- the pixel at x y<br> before = (y * width * 3) + (x * 3) - 3<br>
<br>main = do<br> putStrLn "P6"<br> putStrLn ( (show width) ++ " " ++ (show height) )<br> putStrLn "255"<br> -- Set a red pixel at 100 100<br> B.putStr (setPixel blankImage 100 100 (255,0,0))
<br><br><br>Can I please have some review comments on the code above? Would recreating the entire ByteString for each setPixel be an overhead?<br>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?<br>
<br>Regards,<br>Kashyap<br></div></div><br>
</div><br>_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
<br></blockquote></div><br>