Resizing properly in a world of {default=sRGB}

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
hochgurgler
Posts: 5
Joined: 2010-04-08T01:51:41-07:00
Authentication code: 8675308

Resizing properly in a world of {default=sRGB}

Post by hochgurgler » 2010-04-08T02:56:04-07:00

I've read Eric Brasseur's Gamma article at http://www.4p8.com/eric.brasseur/gamma.html, and I am now miffed with pretty much every graphics tool I have.

Eric has pointed out particularly about resizing, but similar problems would apply to any other operation which does algebraic operations on pixel values. Still, for the time being I'm thinking about resizing.

What I want to know is: Can ImageMagick resize an image taking into account a colour profile which I say that the image has?

Can I say to ImageMagick: Hey ImageMagick, this here image uses the sRGB colour space. Can you resize it to 50% (linear-dimension) and give me back an sRGB image? Oh, and by the way, when you do algebraic operations on pixel values, you must do that in the linear space.

So far the best I have come up with is similar to the example on Eric's page:

Code: Select all

convert in.png -depth 16 -gamma 0.454545454545 -resize 50% -gamma 2.2 -depth 8 out.png
This relies on the fact that the mapping between sRGB and linear can be approximated with a gamma of 2.2. (Also it breaks where the 8-bit input value is 1, because there is insufficient precision in the 16-bit linear space to represent this and it comes out the other side as 0.)

But we know that sRGB actually uses a two zone system whereby the low values are mapped linearly, and higher values use a gamma of 2.4. (Also the linear zone uses a coefficient of 12.92, meaning that 16 bits should be fine for representing the bottom end of the space assuming 8-bit sRGB values.)

So the question is: Rather than approximating with a 2.2 gamma, can we not do it properly and apply the actual defined mappings between sRGB linear space, and if so, how?

And secondarily to that: Given that sRGB is prevalent, why do softwares (including ImageMagick) not assume sRGB by default if no colour profile is present, and act accordingly? i.e. Why do most softwares just assume they can do linear algebraic operations on pixel values when in fact in 2010 most untagged images will be (highly non-linear) sRGB images?

Without wishing to see pre-emptively ungrateful, replies along the lines of "Go and read up about colour profiles" are probably not going to solve my issue. I tried reading about colour profiles but it seemed to end up leaving me with more questions than it answered.

If what I am asking for is possible, then it would be nice to have an example ImageMagick command-line recipe which would do it.

What I am thinking, expressed in fictional (but hopefully obvious-meaning) directives would go as follows:

Code: Select all

# NOTE: pseudo-code! This will not actually work!
convert in.png -depth 16 -convert-sRGB-to-linear -resize 50% -convert-linear-to-sRGB -depth 8 out.png
For the avoidance of doubt, the fictional '-convert-...' directives should apply a transformation to every pixel in the image (and not just change metadata which applies to the image).

Alternatively, it could work as:

Code: Select all

# NOTE: pseudo-code! This will not actually work!
convert in.png -actually-take-account-of-colorspace sRGB -resize 50% -out.png
Where the directive "-actually-take-account-of-colorspace" affects the operation of "-resize" so that "-resize" maps to and from linear space on the fly.

Though of course it could be that I am suffering from an understanding problem, which is scenario I'm prepared to consider given that at the minute it seems to me that there seems to be something of an elephant in the room.

Bill

snibgo
Posts: 11319
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Resizing properly in a world of {default=sRGB}

Post by snibgo » 2010-04-08T20:43:47-07:00

I thought that was the function of "-set colorspace", ie

Code: Select all

convert in.png -set colorspace sRGB -resize 50% out.png
does the resize assuming the pixels of in.png are sRGB, so it will do (roughly) the "-gamma 0.45" before the resize and "-gamma 2.2" after.
snibgo's IM pages: im.snibgo.com

hochgurgler
Posts: 5
Joined: 2010-04-08T01:51:41-07:00
Authentication code: 8675308

Re: Resizing properly in a world of {default=sRGB}

Post by hochgurgler » 2010-04-09T03:16:54-07:00

snibgo wrote:I thought that was the function of "-set colorspace", ie

Code: Select all

convert in.png -set colorspace sRGB -resize 50% out.png
does the resize assuming the pixels of in.png are sRGB, so it will do (roughly) the "-gamma 0.45" before the resize and "-gamma 2.2" after.
Thank-you for replying.

OK that does sound logical. We want to way to say to ImageMagick "This here image uses the sRGB colourspace. Don't touch the pixel values. Just forcibly set the metadata, now, and don't do anything else.", and the documentation for "-set" seems to suggest that this is what it does.

Then in theory ImageMagick should take account of this when it wants to do algebraic operations on pixel values.

So I tried it and it doesn't work --- the Dalai Lama comes out as a grey rectangle again.

So I thought "Well, -resize probably just does algebraic operations on the pixel values, without regard to the linearity of the colourspace. This is thoroughly broken behaviour, but if we understand the breakage, we may be able to work around it".

So logically the workaround would be to convert the image to a linear space, do the resize, then convert it back to the desired space (sRGB).

If we use "-set colorspace" to tell ImageMagic what the colourspace is at the beginning, then we should be able to use "-colorspace" to transform the image pixels to new colourspace (and also flagging that in the image metadata). ImageMagick will have knowledge of both the "coming from" and "going to" colourspaces, and should be able to divine the appropriate transformation.

So logically it should be

Code: Select all

convert gamma_dalai_lama_gray.jpg
    -set colorspace sRGB # Set metadata only; do not touch pixels.
    -depth 16            # Increase image precision.
    -colorspace RGB      # Transform pixels from existing colourspace (sRGB) to
                         # new colourspace (RGB), and update colourspace
                         # metadata to be RGB.
    -resize 50%          # Now that pixels are in a linear space, resize should
                         # be safe.
    -colorspace sRGB     # Transform pixels from existing colourspace (RGB) to
                         # new colourspace (sRGB), and update colourspace
                         # metadata to be sRGB
    -depth 8             # Go back to original precision
    gamma_dalai_lama_gray.50pc.png
Unfortunately this does not even complete and instead give us an error message:

convert: Invalid sRGB rendering intent specified `gamma_dalai_lama_gray.50pc-2.png'.

I am surprised that the obvious thing that everyone would obviously want simply does not work and it is an uphill struggle to get ImageMagick to do the simplest of operations.

Perhaps I will need to analyse ImageMagick at the source code level to get any traction on the issue.

Bill

User avatar
magick
Site Admin
Posts: 10918
Joined: 2003-05-31T11:32:55-07:00

Re: Resizing properly in a world of {default=sRGB}

Post by magick » 2010-04-09T04:34:50-07:00

A great majority of image processing algorithms assume a linear colorspace for correct results. However, the ImageMagick policy / philosophy is to assume the user knows what they are doing and to not do anything automatically. Its up to the user to use the -colorspace option or profiles to convert their images to a linear colorspace before applying image processing algorithms or not.

hochgurgler
Posts: 5
Joined: 2010-04-08T01:51:41-07:00
Authentication code: 8675308

Re: Resizing properly in a world of {default=sRGB}

Post by hochgurgler » 2010-04-09T05:41:46-07:00

magick wrote:A great majority of image processing algorithms assume a linear colorspace for correct results. However, the ImageMagick policy / philosophy is to assume the user knows what they are doing and to not do anything automatically. Its up to the user to use the -colorspace option or profiles to convert their images to a linear colorspace before applying image processing algorithms or not.
Thank-you for your reply.

We now know what the ImageMagick philosophy is.

I am not sure I agree with that philosophy but there is no point arguing that point --- ImageMagick's structure means that the maintainers are free to work according to whatever philosophy they see fit. Rather I would like to try to determine if there is a way of persuading ImageMagick to produce a result according to a straight-down-the-line interpretation of things.

The question is: Given that ImageMagick's "resize" operation assumes that its input image uses a linear colorspace, how can we get ImageMagic to treat an incoming image as sRGB, convert it to a linear color space (at a suitably high precision, e.g. 16-bit), resize it, convert it back to sRGB, convert it back to the desired precision (e.g. 8-bit), and feed out the image to a file (preferably a PNG file)?

As an example, I am using the file at http://www.4p8.com/eric.brasseur/gamma_ ... a_gray.jpg

If I display this image as-is, I can see a picture of the Dalai Lama.

I appear to be using ImageMagick 6.4.0 (04/17/08) Q16.

If I take this file and apply ImageMagick's "-resize 50%", without taking any special precautions, and display the result, I get a (nearly uniform) grey rectangle. Had I picked out a subset of pixels from the original image, this would not be a surprise, but using any sane resizing algorithm which takes account of all of the original image's pixel values should result in the picture being clearly visible in the output.

So something is clearly going wrong.

What appears to be happening is that the values in the image, if averaged algebraically, result in a uniform grey.

The values in the image appear to have been crafted so that this behaviour will result.

I assert that if the image is assumed to be in the sRGB space, and converted to linear space, then resized, then the Dalai Lama is still visible in the resulting image.

We can demonstrate this by wrapping the resize in a pair of gamma operations which approximate the sRGB->linearRGB and linearRGB->sRGB transformations.

But it occurred to me that approximating the transformations was a bit silly considering (a) we know exactly what the transformation is supposed to be, (b) it is the obvious thing that everyone would always obviously want to do, and (c) we shouldn't really have to think about the details of such transformations; any image processing software which claims to have any reasonable support for colorspaces should have these transformations pre-programmed into it as "macros" or "named invocable things" or some such and/or given the likely computational cost of these transformations, have optimised implementations ready to go.

In fact I have gone as far as examining the ImageMagick source code. Indeed there does appear to be code for transforming images between linear RGB and various named colorspaces.

But I am having difficulty trying to determine exactly what incantation will make it actually perform the desired colorspace transformations.

Theoretically, I could examine the source code further, to determine how it works from the command-line UI right through to the colorspace transformations to see if there is a way I can get the desired operations to happen.

But I though I would ask the question first. After all, this is something I should be able to work out by reading the documentation.

One thing in particular that seems not to work in any useful way is using "-set colorspace sRGB" to forcibly re-set the image's colorspace metadata (without touching the pixel data). Interestingly, "-set colorspace" will seem to accept any value following, which makes me wonder if it is actually touching the relevant metadata value at all. (Also "-set" will seem to accept any attribute name as well, so I am not even sure what it does. It is as if "-set" just allows you to specify some attribute-value pairs for no adequately explainable purpose.)

So the question there would be: Does "-set colorspace foo" actually set the images "colorspace" metadata to "foo" (and without touching the image's pixel values), and if not, how can we do this?

The "-colorspace" directive does seem to do something, because it will not accept invalid colorspace names as a parameter, and if you use "-colorspace sRGB" and then try to save as a PNG file, the PNG exporter barfs.

And that is another thing that operates in a very strange and surprising way: The PNG output filter refuses to proceed if the image's colorspace is "sRGB" (i.e. following a "-colorspace sRGB" directive). I thought that most images floating around nowadays use the sRGB colorspace, so not to be able to output an sRGB image to PNG seems to be really badly broken.

Bill

snibgo
Posts: 11319
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Resizing properly in a world of {default=sRGB}

Post by snibgo » 2010-04-09T07:14:31-07:00

Input image (alternating black and white lines): Image

Code: Select all

convert lines.png -resize 50%% lines1.png
lines1.png: Image

Code: Select all

convert lines.png -gamma 0.45454 -resize 50%% -gamma 2.2 lines2.png
lines2.png: Image

Code: Select all

"%IMG%convert lines.png -set colorspace sRGB -resize 50%% lines3.png
lines3.png: Image

On this image, "-set colorspace sRGB" yields a similar result to the gamma conversions.
I assert that if the image [of the Dalai Lama] is assumed to be in the sRGB space, and converted to linear space, then resized, then the Dalai Lama is still visible in the resulting image.
You may assert, but is it true? The image has been created by some rather neat code that redistributes the information in vertically adjacent pixels such that they will then sum arithmetically to exactly grey. So software that resizes (by exactly 50%) without gamma adjustment will yield grey. An interesting effect, but it doesn't prove to me that such software is "wrong".

I don't think that images with no profile should be assumed to be sRGB. First, it would change the effect of so much code and images already out there. Second, if I create an image with pixel values meaning "RGB", I don't want ImageMagick or any other software thinking it knows better. But an option that meant "if the image has no profile, assume a profile of XXXX" (where XXXX was sRGB or anything else) would be okay.
snibgo's IM pages: im.snibgo.com

hochgurgler
Posts: 5
Joined: 2010-04-08T01:51:41-07:00
Authentication code: 8675308

Re: Resizing properly in a world of {default=sRGB}

Post by hochgurgler » 2010-04-09T08:21:01-07:00

snibgo wrote:Input image (alternating black and white lines)

Code: Select all

convert lines.png -resize 50%% lines1.png
lines1.png: { A largely uniform rectangle of pixels #7F7F7F }

Code: Select all

convert lines.png -gamma 0.45454 -resize 50%% -gamma 2.2 lines2.png
lines2.png: { A largely uniform rectangle of pixels #BABABA }

Code: Select all

"%IMG%convert lines.png -set colorspace sRGB -resize 50%% lines3.png
lines3.png: { A largely uniform rectangle of pixels #BBBBBB }

On this image, "-set colorspace sRGB" yields a similar result to the gamma conversions.
I understand the first and second resizes, and they are consistent with my expectations. The first one demonstrates the issue with ignoring this particular flavour of non-linearity: Thin light areas over dark backgrounds are artificially darkened.

But I can't understand what is making the third one return #BBBBBB.

I copy-and-pasted your commands into my system to see what would happen.

On my system, the first two appear the same, but the third one comes out the same as the first, i.e. largely uniform #7F7F7F.

So perhaps ImageMagick's behaviour has changed and I need to be running on a later version.

I am currently running on:

Code: Select all

$ convert -version
Version: ImageMagick 6.4.0 04/17/08 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2008 ImageMagick Studio LLC
over Cygwin 1.7.1.

What are you running on?

(BTW, your original image appears to be a BMP with a ".png" suffix. I don't think it makes any difference to this example.)

Bill

snibgo
Posts: 11319
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Resizing properly in a world of {default=sRGB}

Post by snibgo » 2010-04-09T08:59:37-07:00

Yes, whoops, my bad typing, lines.png is really a bmp file. It doesn't effect the result.

Why is one image hex BA, where the other is hex BB? Because sRGB transformation isn't a simple gamma conversion. See http://www.imagemagick.org/script/comma ... ptions.php under "colorspace" for the calculation IM uses.

I suggest you upgrade IM. Today I am running IM 6.6.0-8 on Windows 7.
snibgo's IM pages: im.snibgo.com

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Resizing properly in a world of {default=sRGB}

Post by NicolasRobidoux » 2011-04-14T22:32:29-07:00

I am still managing to be pretty confused RE: doing resizing in a linear colorspace and then converting back to sRGB.

Does the following code snippet do what I expect, namely:

Step 1: Convert "whatever" to linear (YCbCr) using the input images' color information/profile, if any.

Step 2: Resize and crop.

Step 3: Convert to sRGB, strip (in the hope that a web browser will assume sRGB in the absense of a profile/colorspace info) and save.

?

Is it really that easy?

Code: Select all

# test image from http://www.pbase.com/konascott/image/69543104/original
infile="../69543104.bHSz3aSK.Downsampletestimage.jpg"

size="96x96"
quality="90"
filter="lanczos2sharp"

convert $infile \
-colorspace YCbCr \
-filter $filter -distort resize $size^ \
-gravity Center \
-crop $size+0+0 \
+repage \
-colorspace sRGB \
-sampling-factor 2x2 \
-quality $quality \
-strip \
$size\_$filter\_$quality.jpg
I don't see anything obviously wrong with the result.

hochgurgler
Posts: 5
Joined: 2010-04-08T01:51:41-07:00
Authentication code: 8675308

Re: Resizing properly in a world of {default=sRGB}

Post by hochgurgler » 2011-04-15T02:47:05-07:00

The razor which determines whether this issue is solved is as follows:

We use the test image from Eric Brasseur's page http://www.4p8.com/eric.brasseur/gamma.html :

Image

Resize this image to 50% linear-dimension without using any special flags.

If you get an image which looks like the original but smaller, then ImageMagick does everything correctly automatically. This is good news (though it does mean anyone who is assuming it doesn't and is doing gamma approximation of sRGB will then get it wrong).

If you get a grey rectangle, or one of the various distorted results, then we go on to the next step:

Determine the simplest set of flags on ImageMagick which will do a resize with the right result, preferably treating the input image as sRGB colourspace, and producing an output image with sRGB colourspace.

If the set of flags required to do that is relatively straightforward and intuitive, then we are winning.

If the set of flags required is large, complicated or counter-intuitive, then ImageMagick is still making "the obvious thing which everyone would want" hard.

User avatar
anthony
Posts: 8878
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Resizing properly in a world of {default=sRGB}

Post by anthony » 2011-04-15T07:17:01-07:00

hochgurgler wrote:[If we use "-set colorspace" to tell ImageMagic what the colourspace is at the beginning, then we should be able to use "-colorspace" to transform the image pixels to new colourspace (and also flagging that in the image metadata). ImageMagick will have knowledge of both the "coming from" and "going to" colourspaces, and should be able to divine the appropriate transformation.

So logically it should be

Code: Select all

convert gamma_dalai_lama_gray.jpg
    -set colorspace sRGB # Set metadata only; do not touch pixels.
    -depth 16            # Increase image precision.
    -colorspace RGB      # Transform pixels from existing colourspace (sRGB) to
                         # new colourspace (RGB), and update colourspace
                         # metadata to be RGB.
    -resize 50%          # Now that pixels are in a linear space, resize should
                         # be safe.
    -colorspace sRGB     # Transform pixels from existing colourspace (RGB) to
                         # new colourspace (sRGB), and update colourspace
                         # metadata to be sRGB
    -depth 8             # Go back to original precision
    gamma_dalai_lama_gray.50pc.png
Unfortunately this does not even complete and instead give us an error message:

convert: Invalid sRGB rendering intent specified `gamma_dalai_lama_gray.50pc-2.png'.

I am surprised that the obvious thing that everyone would obviously want simply does not work and it is an uphill struggle to get ImageMagick to do the simplest of operations.

Perhaps I will need to analyse ImageMagick at the source code level to get any traction on the issue.

Bill
The -depth you can ignore, and depth is only used during writes (and occasionaly reads) of image. The depth of input for example is typically preserved.

Other than that the above example appears logical to me, and I would have expected it to work. However PNG I do not think understands colorspace. As such adding -set colorspace RGB just before the final save to PNG should fix the error.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/

User avatar
anthony
Posts: 8878
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Resizing properly in a world of {default=sRGB}

Post by anthony » 2011-04-15T07:22:26-07:00

snibgo wrote:

Code: Select all

"%IMG%convert lines.png -set colorspace sRGB -resize 50%% lines3.png
I believe the only reason this came out correct, was not because the resize worked right, but because when the PNG image was saved it converted from sRGB to RGB.

That is this is what really happened!

Code: Select all

convert lines.png -resize 50%%   -set colorspace sRGB -colorspace RGB  lines3.png
Note the order of actions!

Of course as the input image was simple pure white and black, you would still get the same result as if it was correctly handled.

Maybe correct color space handling should be added as part of IM version 7?

I have not even created a proper examples section about this in IM Examples! :-(

Mind you I'm probably just as much at fault in ignoring correct Gamma, and Colorspace handling as just about everyone else. Especially as most of my real image processing work is often more to do with linear mathematical shapes, (such as morphology) than real life photos.

I can even think of an example where colorspace consideration may be effecting some of my results. EG: Distance with Anti-Aliased Shapes



The real problem is IM has next to no way of knowing if input images are actually gamma corrected sRGB or mathematically linear RGB. There is no one size fits all solution, though if PNG and GIF images automatically set sRGB colorspace for reading and writing, and some commands, like resize, distorts, convolve, morphology, automatically convert sRGB to RGB when it see it, should go a long way to fixing the problem.

Hmmm Question. the SVG and X11 color specifications/ would they be sRGB or RGB values?

WARNING: colorspace changes between sRGB and RGB would not be recommended for IM Q8, which has just too few significant bits to make it practical. But then users of IM Q8 are generally more concerned over other things.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/

Wolfgang Woehl
Posts: 34
Joined: 2010-02-25T15:22:50-07:00
Authentication code: 8675308

Re: Resizing properly in a world of {default=sRGB}

Post by Wolfgang Woehl » 2011-04-15T15:34:43-07:00

magick, I see that magick/colorspace.c is using 0.03928f for K0 (just like the docs at http://www.imagemagick.org/script/comma ... colorspace section sRGB say.) I'm kind of staring at http://en.wikipedia.org/wiki/SRGB#Theor ... sformation which discusses K0 as 0.04045 in order to fix slope continuity. Am I reading this wrong?

User avatar
magick
Site Admin
Posts: 10918
Joined: 2003-05-31T11:32:55-07:00

Re: Resizing properly in a world of {default=sRGB}

Post by magick » 2011-04-15T18:19:37-07:00

It looks like the docs are wrong (we'll correct that). The source code uses 0.04045 for K0.

User avatar
anthony
Posts: 8878
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Resizing properly in a world of {default=sRGB}

Post by anthony » 2011-04-15T21:53:41-07:00

The real problem is IM has next to no way of knowing if input images are actually gamma corrected sRGB or mathematically linear RGB. There is no one size fits all solution, though if PNG and GIF images automatically set sRGB colorspace for reading and writing, and some commands, like resize, distorts, convolve, morphology, automatically convert sRGB to RGB when it see it, should go a long way to fixing the problem.

What about JPEGs that contain no profile? What if a JPEG has an unusual profile? Color profiles and colorspace may need to be more tightly linked. It is no good automatically converting to RGB if the profile does not match when you save it again.

Hmmm Question: Is the SVG and X11 color specifications be in sRGB or RGB values? If we do this then this becomes very important!

WARNING: colorspace changes between sRGB and RGB would not be recommended for IM Q8, which has just too few significant bits to make it practical. But then users of IM Q8 are generally more concerned over other things.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/

Post Reply