All image-editing software gets scaling wrong
4p8.com
4p8.com
In many contexts, RGB values don't have gamma associated with them, just as they don't have ColorSync profiles or whatnot, or if they have one, it was just invented at some stage of processing. (Using the current screen gamma would be pretty arbitrary for an image editor.) Trying to "convert" between different gamma values during processing likely will do more harm than good if your entire pipeline doesn't have this philosophy, or worse, if only one program (e.g. Photoshop) or format (e.g. PNG) does.
I suppose PNG files win a prize for carrying gamma information, so that web browsers and image viewers can apply a curve in software that throws off their brightness and contrast relative to everything around them? And when Photoshop decides the colors in my GIF file need to be "converted" to sRGB from god-knows-what it thinks they were before?
If you want every last image operation to be done with perceptual accuracy, convert your images to some fancy color space like CIELAB, after careful consideration of their intended source gamma and color space, and do your calculations there; then somehow be sure they are accurately converted for display on the user's monitor.
Even assuming a gamma of 1.8 would mean less loss of detail when scaling down, even when the eventual viewer is eg using 2.2.
http://www.4p8.com/eric.brasseur/gamma.html#explanation
Basically, if you have a test image which consists of alternating black and white, it should have the same perceived brightness when you scale it down - but when you scale it down, the software needs to average out the black and white. If it does a simple arithmetic average, it'll probably choose 127,127,127 once it's downscaled enough to become uniform in color. But if you compare that uniform color with the original black and white lines, it looks a different shade - a darker shade. That's because 127,127,127 isn't 50% grey, it's not in the middle between black and white.
The article has further explanation.
$ foo()
> {
> wget -qO- "${1?}" |
> sed -n '/.*title"/!d; s///; s/">.*//; s/.*"//p; q'
> }
$ cat <(foo 'http://news.ycombinator.com/item?id=1141971') \
> <(foo 'http://news.ycombinator.com/item?id=1523991') |
> uniq -c
2 http://www.4p8.com/eric.brasseur/gamma.html
$CCDs are definitely less than ideal as a sensor, unless you've calibrated the specific unit you are using and apply a correction curve you can definitely expect some non-linearity.
Some professional grade CCDs apply a correction internally before passing the data to the consumer.
Sources of non-linearity are blooming (the leakage of current from brightly lit cells to dark cells nearby), AD non-linearity and temperature effects.
I'm assuming you are talking about a professional grade CCD with an internal correction, but the blooming issues are part and parcel of the medium and when you have high contrast images as input you really have to be aware of that.
For giggles I fired up pro compositing tool Nuke (www.thefoundry.co.uk), which has a choice of 8 resize algorithms, and 7 of them get it right.
What that means? I guess that Photoshop isn't really really a professional app.
Talking about a problem is nice, but fixing it is even better.
Link to examples: http://www.4p8.com/eric.brasseur/gamma_dalai_lama.html
Why couldn't we have graphics cards, monitors, printers, cameras, camcorders and other devices that perform mapping from linear values to exponential values (or vice versa)? Then linear scale would be the standard and all software could continue to live on the nice and comfortable illusion that 127 is half the brightness of 255 and everyone would be happy. It's just that when a pixel of value 127 was shown on the screen it would actually show up as what we currently get from 180 or so.
Using 127.5 to represent half and 255 to represent 1 is completely unintuitive.
For the second point, programmers are familiar with base-2. For decimal values, both end-users and programmers confuse 127/128 vs. 255/256 for being half the latter. Besides, end-users often see [0.0, 1.0] floating point range for color values already in graphics user interfaces, and would expect 0.5 to give half the intensity that does 1.0.
For showing the amount in each component to users, it's possible to use either linear or gamma-compressed values, depending on the goal, but either way showing a decimal makes it a lot easier to understand than showing a fraction of 255.
Currently, if 180 out of 256 is half then we have considerably fewer values representing the highest intensities than the darkest intensities. So, in effect we currently "waste" values by allocating lots of them for darker values that mostly seem all the same on the screen. If we could program on the linear scale, it would depend on the hardware that how accurately the linear scale would be mapped to the voltages that would give linear intensity levels in reality.
You can add bits per channel if you want more precision, that's what we do already.
There’s a not great description at http://en.wikipedia.org/wiki/Lightness_(color)
This is why I'm not convinced that the right solution is simply filtering in linear intensity. Consider a black and white checker board where the individual squares are big enough that you can easily see them. If you scale this image down such that the squares disappear, the resulting gray should be the one that minimizes the perceptual error.
But since sRGB is roughly perceptually uniform and the squares are mostly low frequency information, that gray would be 0x80 and not the 0xba you would get from the supposedly correct algorithm.
When working in a space that has any profile burned in, all non-floating point data must also be promoted to a wider bit depth than the input or else the linearization will introduce banding.
As memory (RAM) used to be scarce when people started writing such programs, the fact this problem exists still nowadays imho is twofold:
(1) lack of understanding of the problem per se and (2) [hardware & processing] constraints of the systems such software ran on, 15 years ago.
Neither is an excuse of course.
http://www.opengl.org/registry/specs/EXT/texture_sRGB.txt
http://www.opengl.org/registry/specs/ARB/framebuffer_sRGB.tx...
See this, for example:
http://www.x.org/docs/AMD/R5xx_Acceleration_v1.5.pdf
Bit 21 of TXFORMAT0:
GAMMA 21 none Optionally remove gamma from texture before passing to
shader. Only apply to 8bit or less components.
POSSIBLE VALUES:
00 - Disable gamma removal
01 - Enable gamma removal
There is also support for re-applying gamma before storing to a color buffer.Might be worth trying to use the CATiledLayer stuff and the CoreImage scaling to generate 'live' scaling. That might work better than whatever Safari, UIKit and the GPU presently do.
I'll write to the Irfanview author but I don't know if there would be any change soon.