[Haskell-cafe] Right way to implement setPixel function

Job Vranish jvranish at gmail.com
Thu Aug 20 13:13:40 EDT 2009


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 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,
> 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 at 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 at haskell.org
>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20090820/55b79cc8/attachment.html


More information about the Haskell-Cafe mailing list