
Hi, Now that I've understood how to generate raster points of a line in Haskell - the next thing I want to do is generate a pnm file with it. I've done it in perl as of now. In perl, I can have a scalar variable $x contain a string of 256*256*3 bytes (for 24-bit 256x256 image) and set pixels using substr on LHS. I was wondering how I could do something similar in Haskell? sub setPixel{ my($x,$y,$red,$green,$blue)=@_; my$pixel=pack "CCC",$red,$green,$blue; my$offset=$WIDTH*$y*3 + $x*3; substr($image,$offset,3) = $pixel; } Regards, Kashyap

On Sun, Aug 2, 2009 at 4:00 PM, CK Kashyap
Hi, Now that I've understood how to generate raster points of a line in Haskell - the next thing I want to do is generate a pnm file with it. I've done it in perl as of now. In perl, I can have a scalar variable $x contain a string of 256*256*3 bytes (for 24-bit 256x256 image) and set pixels using substr on LHS. I was wondering how I could do something similar in Haskell?
sub setPixel{ my($x,$y,$red,$green,$blue)=@_; my$pixel=pack "CCC",$red,$green,$blue; my$offset=$WIDTH*$y*3 + $x*3; substr($image,$offset,3) = $pixel; }
There's a library on hackage which does this http://hackage.haskell.org/package/ppm You can install this by doing
cabal install ppm
Here's an example usage (this uses the binary version of ppm, the docs for ppm has an example for the ASCII version): writePPM fname img = withBinaryFile fname WriteMode (\h -> hPutStr h (ppm_p6 img) ) If you're looking for the learning experience, you could always read the source for the library (which is pretty tiny). -- Sebastian Sylvan +44(0)7857-300802 UIN: 44640862

Thanks Sebastian,
ppm module is indeed very useful. So, I guess my question then just boils down to, how can I write a function to mimic the setPixel function ->
Basically, a blank white image would look like this (as per ppm module)
[
[ (255, 255, 255) , (255, 255, 255) , (255, 255, 255) ] , -- 3 columns of row 1
[ (255, 255, 255) , (255, 255, 255) , (255, 255, 255) ] --- 3 columns of row 2
]
setPixel x y r g b when called like this - setPixel 0,0,255,0,0
[
[ (255, 0, 0) , (255, 255, 255) , (255, 255, 255) ] , -- 3 columns of row 1
[ (255, 255, 255) , (255, 255, 255) , (255, 255, 255) ] --- 3 columns of row 2
]
What would be a good way to implement such a function?
Regards,
Kashyap
________________________________
From: Sebastian Sylvan
Now that I've understood how to generate raster points of a line in Haskell - the next thing I want to do is generate a pnm file with it. I've done it in perl as of now. In perl, I can have a scalar variable $x contain a string of 256*256*3 bytes (for 24-bit 256x256 image) and set pixels using substr on LHS. I was wondering how I could do something similar in Haskell?
sub setPixel{ my($x,$y,$red,$green,$blue)=@_; my$pixel=pack "CCC",$red,$green,$blue; my$offset=$WIDTH*$y*3 + $x*3; substr($image,$offset,3) = $pixel; }
There's a library on hackage which does this http://hackage.haskell.org/package/ppm You can install this by doing
cabal install ppm
Here's an example usage (this uses the binary version of ppm, the docs for ppm has an example for the ASCII version): writePPM fname img = withBinaryFile fname WriteMode (\h -> hPutStr h (ppm_p6 img) ) If you're looking for the learning experience, you could always read the source for the library (which is pretty tiny). -- Sebastian Sylvan +44(0)7857-300802 UIN: 44640862

On Mon, Aug 3, 2009 at 6:38 AM, CK Kashyap
Thanks Sebastian, ppm module is indeed very useful. So, I guess my question then just boils down to, how can I write a function to mimic the setPixel function ->
Basically, a blank white image would look like this (as per ppm module) [ [ (255, 255, 255) , (255, 255, 255) , (255, 255, 255) ] , -- 3 columns of row 1 [ (255, 255, 255) , (255, 255, 255) , (255, 255, 255) ] --- 3 columns of row 2 ]
setPixel x y r g b when called like this - setPixel 0,0,255,0,0
[ [ (255, 0, 0) , (255, 255, 255) , (255, 255, 255) ] , -- 3 columns of row 1 [ (255, 255, 255) , (255, 255, 255) , (255, 255, 255) ] --- 3 columns of row 2 ]
What would be a good way to implement such a function?
Well you could start by writing a function like: adjustElem :: Int -> ( a -> a ) -> [a] -> [a] That would basically apply a function to a specific element in a list (indexed by the first parameter). Look at splitAt in Data.List, it may be useful. Then you can use this in a nested way, by calling adjustElem to modify the row you're interested in, and the function you pass in to adjust that row would in turn call adjustElem on the specific pixel in that row). However, this may be very slow. If you don't care about speed it'll work fine, but if you really do want to build up an image by successive single-pixel modifications, you should consider first using an Array and accumArray, this will be much faster as internally accumArray can use a mutable array (while the external interface is still pure). Sebastian

Thanks Sebastian,
Array/accumArray sounds like what I am looking for.
Int -> ( a -> a ) -> [a] -> [a]
approach, would it not be expensive on memory as well? Or is it just speed?
Regards,
Kashyap
________________________________
From: Sebastian Sylvan
ppm module is indeed very useful. So, I guess my question then just boils down to, how can I write a function to mimic the setPixel function ->
Basically, a blank white image would look like this (as per ppm module) [ [ (255, 255, 255) , (255, 255, 255) , (255, 255, 255) ] , -- 3 columns of row 1 [ (255, 255, 255) , (255, 255, 255) , (255, 255, 255) ] --- 3 columns of row 2
]
setPixel x y r g b when called like this - setPixel 0,0,255,0,0
[ [ (255, 0, 0) , (255, 255, 255) , (255, 255, 255) ] , -- 3 columns of row 1 [ (255, 255, 255) , (255, 255, 255) , (255, 255, 255) ] --- 3 columns of row 2
]
What would be a good way to implement such a function?
Well you could start by writing a function like: adjustElem :: Int -> ( a -> a ) -> [a] -> [a] That would basically apply a function to a specific element in a list (indexed by the first parameter). Look at splitAt in Data.List, it may be useful. Then you can use this in a nested way, by calling adjustElem to modify the row you're interested in, and the function you pass in to adjust that row would in turn call adjustElem on the specific pixel in that row). However, this may be very slow. If you don't care about speed it'll work fine, but if you really do want to build up an image by successive single-pixel modifications, you should consider first using an Array and accumArray, this will be much faster as internally accumArray can use a mutable array (while the external interface is still pure). Sebastian

On Mon, Aug 3, 2009 at 11:17 AM, CK Kashyap
Thanks Sebastian, Array/accumArray sounds like what I am looking for.
Int -> ( a -> a ) -> [a] -> [a] approach, would it not be expensive on memory as well? Or is it just speed?
Well memory will be garbage collected fairly quickly so I don' think that's an issue, other than the effects on speed that the extra allocations would have. It's probably mainly speed because each pixel would have time complexity O(n+m) rather than O(1) for an n*m image... -- Sebastian Sylvan +44(0)7857-300802 UIN: 44640862
participants (2)
-
CK Kashyap
-
Sebastian Sylvan