Hi! I have lots and lots of images (jpegs) that I would like to manipulate and shrink (in size). They are around 5 Mb big, so I thought this would be a good Haskell project since its a lazy evaluating language. The problem is that I cant find any libraries for image manipulation. Anyone who knows something that would interest me and maybe give me some advices? Best regards, Bjorn.
listuser07:
Hi! I have lots and lots of images (jpegs) that I would like to manipulate and shrink (in size). They are around 5 Mb big, so I thought this would be a good Haskell project since it's a lazy evaluating language. The problem is that I can't find any libraries for image manipulation. Anyone who knows something that would interest me and maybe give me some advices?
check on hackage.haskell.org. There's gtk and imlib, at least. Using bytestrings also makes sense here. -- Don
On Oct 29, 2007, at 21:40 , Don Stewart wrote:
listuser07:
Hi! I have lots and lots of images (jpegs) that I would like to manipulate and shrink (in size). They are around 5 Mb big, so I thought this would be a good Haskell project since it's a lazy evaluating language. The problem is that I can't find any libraries for image manipulation. Anyone who knows something that would interest me and maybe give me some advices?
check on hackage.haskell.org. There's gtk and imlib, at least. Using bytestrings also makes sense here.
There's also the GD binding: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/gd I wrote it to be able to do image resizing and scaling in the photo album module for Hope, http://hope.bringert.net/ /Björn
On 10/29/07, Björn Wikström <listuser07@gmail.com> wrote:
Hi! I have lots and lots of images (jpegs) that I would like to manipulate and shrink (in size). They are around 5 Mb big, so I thought this would be a good Haskell project since it's a lazy evaluating language. The problem is that I can't find any libraries for image manipulation. Anyone who knows something that would interest me and maybe give me some advices?
It's not released yet, but I'm working on a set of Haskell bindings for the ImageMagick library. If people are interested in using what I have so far / helping work on it, I can upload the code somewhere. Cheers, Tim -- Tim Chevalier * catamorphism.org * Often in error, never in doubt "I soon discovered that if you keep your mouth shut, people are apt to believe you know everything, and they begin to feel freer and freer to tell you anything, anxious to show that they know something, too."--Audre Lorde
[iso-8859-1] Bj�rn Wikstr�m writes:
Hi! I have lots and lots of images (jpegs) that I would like to manipulate and shrink (in size). They are around 5 Mb big, so I thought this would be a good Haskell project since its a lazy evaluating language. ...
I must say that I don't see much use of laziness here. In any language you can read an image as incrementally as its format permits to do, but anyway some solid chunks must be present in the memory, in order to do the filtering, the index mapping, or whatever, in order to resize (or rotate, or...) the image. Actually, filling the memory with thunks may degrade the performance of an image processing tool... Jerzy Karczmarczuk
Laziness plays a big role in real world image processing. Typically, in applications like Apple's Shake, you build a dataflow representation of the image processing operations you wish to perform, and the final result is computed lazily so as to reduce the amount of computation. For example, if you blur an image, and then zoom in on the top left corner, then only the top left corner will be loaded up from the original image (assuming your image file format supports tiled access). You still work on tiles or scan-lines, rather than individual pixels, so the laziness has a 'coarse' granularity. But I'm not sure if this is what the original poster was talking about. -- Dan On 10/29/07, jerzy.karczmarczuk@info.unicaen.fr <jerzy.karczmarczuk@info.unicaen.fr> wrote:
[iso-8859-1] Bj�rn Wikstr�m writes:
Hi! I have lots and lots of images (jpegs) that I would like to manipulate and shrink (in size). They are around 5 Mb big, so I thought this would be a good Haskell project since it's a lazy evaluating language. ...
I must say that I don't see much use of laziness here.
Dan Piponi <dpiponi@gmail.com> wrote:
On 10/29/07, jerzy.karczmarczuk@info.unicaen.fr wrote:
I must say that I don't see much use of laziness here. Laziness plays a big role in real world image processing.
vips/nip2 is one nice instantiation of this idea. -- Edit this signature at http://www.digitas.harvard.edu/cgi-bin/ken/sig I want to propose an operating system that will substantially reduce the time required to get a problem solved... The only way quick response can be provided at bearable cost is by time-sharing. That is, the computer must attend to other customers while one customer is reacting to some output.McCarthy,1959.
Dan Piponi adds to a short exchange:
jerzy.karczmarczuk:
[iso-8859-1] Bj�rn Wikstr�m writes:
Hi! I have lots and lots of images (jpegs) that I would like to manipulate and shrink (in size). They are around 5 Mb big, so I thought this would be a good Haskell project since it's a lazy evaluating language. ... I must say that I don't see much use of laziness here.
Laziness plays a big role in real world image processing. Typically, in applications like Apple's Shake, you build a dataflow representation of the image processing operations you wish to perform, and the final result is computed lazily so as to reduce the amount of computation. For example, if you blur an image, and then zoom in on the top left corner, then only the top left corner will be loaded up from the original image (assuming your image file format supports tiled access). You still work on tiles or scan-lines, rather than individual pixels, so the laziness has a 'coarse' granularity.
But I'm not sure if this is what the original poster was talking about.
I am neither... Still, Dan, I think that there is quite a difference between incremental processing of signals, and images, etc., and the *lazy evaluation* of them. Of course, a stream is consumed as economically as it can, but not less. If you filter an image (shrinking, so some low-pass MUST be done), a pixel must be loaded with its neighbourhood, which means *some* scan lines. With a JPEG this means that a 8x8 block should be loaded also with its vicinity. But would you suggest that individual pixel processors should be lazy? It would be useless, and probably resulting in some penalties. So, the laziness of Haskell for me here is less than useful. Noooow, the lazy *generation* of streams is another story... Generating music (low level, i.e. sound patterns) through lazy algorithms is quite interesting. Jerzy Karczmarczuk
Jerzy Karczmarczuk:
Dan Piponi adds to a short exchange:
jerzy.karczmarczuk:
[iso-8859-1] Bjᅵrn Wikstrᅵm writes:
Hi! I have lots and lots of images (jpegs) that I would like to manipulate and shrink (in size). They are around 5 Mb big, so I thought this would be a good Haskell project since it's a lazy evaluating language. ... I must say that I don't see much use of laziness here.
Laziness plays a big role in real world image processing. Typically, in applications like Apple's Shake, you build a dataflow representation of the image processing operations you wish to perform, and the final result is computed lazily so as to reduce the amount of computation. For example, if you blur an image, and then zoom in on the top left corner, then only the top left corner will be loaded up from the original image (assuming your image file format supports tiled access). You still work on tiles or scan-lines, rather than individual pixels, so the laziness has a 'coarse' granularity.
But I'm not sure if this is what the original poster was talking about.
I am neither... Still, Dan, I think that there is quite a difference between incremental processing of signals, and images, etc., and the *lazy evaluation* of them. Of course, a stream is consumed as economically as it can, but not less. If you filter an image (shrinking, so some low-pass MUST be done), a pixel must be loaded with its neighbourhood, which means *some* scan lines. With a JPEG this means that a 8x8 block should be loaded also with its vicinity. But would you suggest that individual pixel processors should be lazy? It would be useless, and probably resulting in some penalties.
So, the laziness of Haskell for me here is less than useful. Noooow, the lazy *generation* of streams is another story... Generating music (low level, i.e. sound patterns) through lazy algorithms is quite interesting.
Wait, Jerzy. Haskell implementations do not have to be lazy as long as they preserve the more abstract semantics. Optimistic evaluation has been considered, for instance by Robert Ennals. My former PhD student Karl-Filip Faxen studied optimizations based on "cheap eagerness", simple cases where it is easy to see that it pays off to generate code that is not totally lazy. One case is if we know that a computation always terminates and takes little time, then it can typically pay off to perform that computation optimistically even in cases where a lazy evaluation strategy might have avoided it. For image processing, if we know that individual pixel computations terminate then the compiler is free to carry (a finite number of) them out in any order, even if some of them turn out not to be needed. So tiled computation schemes are certainly possible, even if parts of some tiles fall outside the final image. Another thing is that current Haskell compiler don't work like this. But Haskell itself does not prevent it. A number of years back I worked on something called the "data field model", a kind of generalized array construct intended for high-level data parallel programming. We also defined and implemented a dialect of Haskell called "Data Field Haskell" which extended Haskell with one particular instance of data fields. Data Field Haskell had a function to force the evaluation of all elements in a data field at once. The purpose of this function was exactly to make possible computations like the above, where it pays off to evaluate data fields, or parts of them, in a non-lazy fashion. I am quite confident that it would be easy to express the image processing mentioned above in Data Field Haskell. Alas, we were never able to do anything else than a proof-of-concept implementation. If anyone is interested to see what we did, there was a paper in the Haskell Workshop 2000. Björn Lisper
Bjorn Lisper <lisper@it.kth.se> writes:
Wait, Jerzy. Haskell implementations do not have to be lazy as long as they preserve the more abstract semantics. Optimistic evaluation has been considered, for instance by Robert Ennals.
I'm not sure if the GC hack proposed by Wadler¹ that lets the garbage collector replace "fst (a,b)" with "a" (and similar for other unchecked selectors) counts as optimistic evaluation, but I wonder what the status of this is. GHC doesn't seem to do it, and I wonder if there is any particular reason? Too specific? As I've posted about previously, I use concurrency to work around the space leak, but it'd be nice to be able to do without, especially as -smp is not compatible with -prof. -k ¹) http://citeseer.ist.psu.edu/wadler87fixing.html -- If I haven't seen further, it is by standing in the footprints of giants
On Wed, Oct 31, 2007 at 10:58:40AM +0100, Ketil Malde wrote:
Bjorn Lisper <lisper@it.kth.se> writes:
Wait, Jerzy. Haskell implementations do not have to be lazy as long as they preserve the more abstract semantics. Optimistic evaluation has been considered, for instance by Robert Ennals.
I'm not sure if the GC hack proposed by Wadler¹ that lets the garbage collector replace "fst (a,b)" with "a" (and similar for other unchecked selectors) counts as optimistic evaluation, but I wonder what the status of this is. GHC doesn't seem to do it, and I wonder if there is any particular reason? Too specific?
GHC nominally does do it (look for 'selector thunks' in the RTS and commentary), but it doesn't work and we don't know why. http://hackage.haskell.org/trac/ghc/ticket/1038 Stefan
Stefan O'Rear wrote:
On Wed, Oct 31, 2007 at 10:58:40AM +0100, Ketil Malde wrote:
Bjorn Lisper <lisper@it.kth.se> writes:
Wait, Jerzy. Haskell implementations do not have to be lazy as long as they preserve the more abstract semantics. Optimistic evaluation has been considered, for instance by Robert Ennals. I'm not sure if the GC hack proposed by Wadler¹ that lets the garbage collector replace "fst (a,b)" with "a" (and similar for other unchecked selectors) counts as optimistic evaluation, but I wonder what the status of this is. GHC doesn't seem to do it, and I wonder if there is any particular reason? Too specific?
GHC nominally does do it (look for 'selector thunks' in the RTS and commentary), but it doesn't work and we don't know why.
GHC HEAD has a fix for the example in that ticket, and 6.8.1 has a workaround (I bumped the recursion depth limit enough to make it run in constant space). Do you have an example that still doesn't work, particularly with the HEAD? Cheers, Simon
On 10/29/07, Björn Wikström <listuser07@gmail.com> wrote:
Hi! I have lots and lots of images (jpegs) that I would like to manipulate and shrink (in size). They are around 5 Mb big, so I thought this would be a good Haskell project since it's a lazy evaluating language. The problem is that I can't find any libraries for image manipulation. Anyone who knows something that would interest me and maybe give me some advices?
Haskell is a wonderful language, so I hate to say this...but personally I don't see the benefit of using Haskell here, unless the manipulations you want to do are very complex. Some simple shell (or perl/python/ruby/whatever) scripts to glue together some calls to convert (or possibly other ImageMagick utilities) ought to do the job just fine. -Brent
participants (12)
-
Bjorn Bringert -
Bjorn Lisper -
Björn Wikström -
Brent Yorgey -
Chung-chieh Shan -
Dan Piponi -
Don Stewart -
jerzy.karczmarczuk@info.unicaen.fr -
Ketil Malde -
Simon Marlow -
Stefan O'Rear -
Tim Chevalier