So, I've been working on an image viewer for Mac OS. This uses Quicktime to load its images. However, Quicktime is a bit limited when it comes to loading more obscure image formats, and it is also a royal pain in the ass to use.
So I was wondering what image loading libraries there are out there. So here's a thread for discussing image loading in general!
Personally, I wouldn't mind replacing Quicktime with something better. What I'd want is something is:
I don't hold out much hope for anything like this actually existing, though.
I was going to suggest Imlib 1 or 2, but neither is thread-safe.
I looked a bit at Imlib, but it seems to just use the standard external dependencies and doesn't seem to make any attempt to be fast at loading. Also, it keeps mentioning X and I wonder if it's not too tightly tied into the X libraries to be useful.
I don't know about that. Imlib was written by the Enlightenment folks, and we know just how crazy they are about performance.
Mind you, loader_jpeg.c doesn't look particularly special in any way (other than having almost no comments). What are they bragging about? Performance of all the other operations?
> What are they bragging about? Performance of all the other operations?
Sure looked that way to me when I looked at it. Loading seems to be mostly done by external libraries...
Why is it that everybody uses libjpeg? I mean, it's a reference implementation, isn't it? It's not a bad reference implementation, but it sure can (and has) been improved on. Why does everyone think there's just the one way of loading JPEGs?
From what I gathered a few years back, LIBJPEG was the only one that was free, complete and portable. They were other implementations but they were either incomplete, unreliable, pinned to one OS and/or commercial/not free.
Has this changed nowadays?
Which other implementation is free, complete and portable?
I think the reason libjpeg is used is because it's mature and trusted. When was the last time it contained a bug or overflow?
That said, you might find Epeg interesting, if only for ideas. It gains a speedup by only considering necessary pixels.
I also came across this: http://openil.sourceforge.net/ . I'm a bit confused though because I read somewhere that its dependencies to libjpeg were removed, but the source definitely uses libjpeg.
Well, for me, all pixels are necessary. libjpeg already can do fast loading of scaled-down versions by not using all data. But it's of no use to me.
DevIL doesn't seem very threadsafe. It also says:
> Choose whether to use the Intel Jpeg Library or libjpeg.
The Intel Jpeg Library is suppoed to be very good, and it used to be free. I wanted to use it once back in the day, and found out it was no longer free. And of course, I doubt it'd do much good on a Mac.
I just ran xzgv, which uses libjpeg, through a directory containing 750 jpegs, with a range of 400x300 to 1600x1400 pixels. It took 105 seconds to fully render all of them (so, about 7fps) on a 1.6GHz Athlon.
If you preload images and also allow operations to be interrupted, surely this would fast enough? It's a far cry from a certain viewer, but it's not that bad.
If you're really slick, you could switch to linearly scaled-up images that were loaded with some variant of epeg hackery once you're going faster than libjpeg can handle.
759 images (95% jpg, 3% png, 2% gif). Precached the files on each OS. Average of three runs:
xzgv (libjpeg 6.2): 90sec (8.4 fps)
acdsee 2.43: 67sec (11.3 fps)
Interesting. How about a test run with only really, really big JPEGs for comparison, to see how much is taken up by the actual JPEG decompression?
The results this time were strange.
200 JPEGs, 157KB-4719KB, 1875x1688-6030x8634.
xzgv: 103sec (1.94 fps)
acdsee (low): 110sec (1.81 fps)
xzgv (cj): 114sec (1.75 fps)
acdsee (high): 137sec (1.46 fps)
xzgv is normal mode, while xzgv (cf) uses the --careful-jpeg option. acdsee (low) is one cluster of datapoints (112sec, 110sec, 109sec), while acdsee (high) is another (137sec, 140sec, 135 sec).
There is no difference between acdsee low and high, other than a few minutes between the two runs. While xzgv was always consistent, acdsee was not. I suspect the variation was a result of Window's CPUfreq governor lowering the frequency to cool the CPU, although I haven't confirmed that.
Whoops.
xzgv: 103sec (1.94 fps)
acdsee (low): 110sec (1.81 fps)
xzgv (cj): 114sec (1.75 fps)
acdsee (high): 137sec (1.46 fps)
I suppose this supports "interface is everything"?
Now, that really is surprising. I would agree with the conclusion in >>14, then.
Well, one more factor: Were these images loaded and shown pixel-for-pixel, or were they scaled to fit on screen? Was the behaviour the same for both programs?
Both displayed fully-rendered unscaled images with no post-processing. As far as I can tell, the behaviour of the two was as identical as could be made. I even disabled acdsee's cache-behind, although it should have no real effect.
I didn't have any programs in the background, other than the normal daemons/services, which were minimal (XFCE and XP).
That said, I cannot guarantee that the images were fully-rendered, given that I wasn't scrolling around in them. However, xzgv spent a long time decoding all the right images (some of them took 4sec on both viewers), so I doubt it was cutting corners.
xzgv's screen space was ~10% smaller than acdsee's, due to the WM (both were windowed). If I repeat this, I'll try to get it fullscreen.
I did have one acdsee run that was 90sec, but I think I mistimed it. Assuming that it was real, 90sec still is not as much faster as I would have expected.
You might want to try FFmpeg. If you disable all the encoders and most of the other stuff, dead code stripping should make it reasonably small, and it can actually use Altivec for JPEG decoding.
> Both displayed fully-rendered unscaled images with no post-processing.
What about the YUV->RGB upsample and matrix multiplying? That's kind of postprocessing.
Unless it uses Xv/OpenGL, I guess.
Hmm, that does sound somewhat tempting. I'll have to look into it.
Ok, after considering this, I have come to some new conclusions.
One is that I do not wish to keep using Quicktime, because it's a pain in the ass. That means I would like an image loading library that loads both the popular formats (JPEG, PNG, GIF), and as many less popular formats as possible (I've personally got files in PSD, TIFF, BMP, PCX, TGA and ILBM, and I'm sure there are several other that it would be nice to support). I've given up on the idea of finding a fast library (unless I start splicing in code from FFmpeg - not an impossible idea), so now I just want something that is not too huge and loads a large number of formats. Also, still threadsafe.
Another feature that would be nice to have, but which I may also have to give up on in, is to load JPEGs into YUV data and letting OpenGL handle that on its own (I've not checked how likely this is to work, but it would save on time and memory).
ImageMagick is the obvious candidate, I guess, if it will slim down enough if you don't use the image processing features. I'll need to do some experiments on that. However, I don't know if it can do the YUV trick.
Any other candidates? I looked at DevIL but decided that the project is dead, and that I don't much like the OpenGL-inspired API anyway. And it's only barely threadsafe.
On second thought: I see no way to interrupt image loading in ImageMagick, which is another must-have feature for this project.
Well, like VacBob pointed out, there's still FFmpeg. FFmpeg has been used by people porting away from Quicktime.
Since you're going to be distributing a binary for most platforms anyway, you can leave most optional dependencies out.
Yeah, but FFmpeg only does JPEG, PNG and GIF. I need the rest, too.