Page 1 of 1

Image conversion 8b -> 16b without darkening - SOLVED

Posted: 2016-11-12T19:25:25-07:00
by 4shades
Hi everyone,

I am using ImageMagick v6.8.1-6 in a PHP application (using exec() system calls to run ImageMagick executables) on a Windows platform.

One task I am trying to do is take an existing 8-bit sRGB image and convert it to 16-bit RGB. These are always grayscale images, that is R=G=B for each pixel. I have developed a simple set of command line arguments that do this, but the conversion process darkens the image significantly and I would like to know if I can avoid or reverse the darkening somehow.

The command I am using is

Code: Select all

convert img_8b.png -colorspace RGB -depth 16 img_16b.png
As an example, here is the BEFORE image (8-bit sRGB)
Image

and here is the AFTER image (16-bit RGB)
Image

For some strange reason these images look almost identical in my Firefox, but very different in IE11. When downloaded, they appear light and dark respectively in Windows, Photoshop etc.

Any ideas or hints to help this newbie?

Cheers,
4Shades

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-12T20:15:18-07:00
by fmw42
try

Code: Select all

convert img_8b.png -colorspace sRGB -depth 16 img_16b.png
or simply

Code: Select all

convert img_8b.png -depth 16 img_16b.png
RGB is linear and darker than non-linear sRGB

It works fine for me on IM 6.9.6.4 Q16 Mac OSX, however, it is still 8-bit grayscale.

So to get it 16 bits, try

Code: Select all

convert im_8b.png -define png:bit-depth=16 img_16b.png
That works for me

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-12T21:44:04-07:00
by snibgo
As Fred says.
4shades wrote:For some strange reason these images look almost identical in my Firefox, but very different in IE11. When downloaded, they appear light and dark respectively in Windows, Photoshop etc.
The reason different programs show the image differently is that your "after" image is encoded in linear RGB, and contains metadata that says this. Software should read that metadata and do any necessary processing. However, some software ignores the metadata and assumes (wrongly) that the image is encoded as non-linear sRGB, so the displayed image is too dark.

But you don't want linear RGB, so shouldn't convert to that colorspace.

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T00:15:35-07:00
by 4shades
Thanks guys, very helpful, Fred's simple command works. :D

Taking up the point about sRGB vs RGB, going from sRGB to RGB tends to darken things. If I did want to convert faithfully to RGB (or Grayscale) I suppose I would have to transform each pixel from sRGB into RGB in such a way as to maintain the input histogram in the output. I can do this, just a little compute-intensive for 1024x1024 images. Or is there a canned tool/option for doing this?

Cheers,
4Shades

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T00:37:37-07:00
by snibgo
4shades wrote:If I did want to convert faithfully to RGB (or Grayscale) I suppose I would have to transform each pixel from sRGB into RGB in such a way as to maintain the input histogram in the output.
I don't understand your query.

"-colorspace RGB" faithfully converts the colorspace to linear RGB. The difficulty is that some software doesn't understand linear RGB.

If you want grayscale, "-colorspace Gray" will do that. But it will still be encoded as sRGB, not linear RGB.

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T01:30:38-07:00
by fmw42
You can also use

-grayscale rec709luminance or rec601luminance

to get linear grayscale. But both will be darker than the equivalent sRGB non-linear.

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T01:56:31-07:00
by 4shades
Sorry to be so obscure! Here are the histograms of the two images:

8-bit
Image

16-bit
Image

You can see that in the 16-bit image (linear RGB) the histogram is shifted to the left, making the image look darker than the nonlinear sRGB in 8 bits. All these images are generated mathematically, so to make a "faithful" transformation to a linear RGB or grayscale colorspace in 16 bits I will need to re-calculate pixel values to replicate the 8-bit histogram. Then the 8-bit and 16-bit images will both look the same, which is what I need.

I want to thank you for having this discussion with me - it has helped me understand the necessary steps in what I am trying to do.

Cheers,
4Shades

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T02:08:29-07:00
by snibgo
But the encodings are different. This means the numbers mean different things.

20% gray encoded in linear sRGB is the same shade of gray as about 3% encoded as non-linear RGB.

Why do you want linear RGB? Do you really want it?

If you want the same histograms, then don't convert to linear.

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T02:45:33-07:00
by 4shades
The reason I want this is that the final 16-bit image will be fed into a third-party image analysis program to generate a digital terrain; the third party program wants 16-bit grayscale and there are no settings I can tweak to get the program to accept a different encoding.

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T02:58:58-07:00
by snibgo
Your image is already grayscale. Fred's command creates a 16-bit version of this. His command doesn't a linear RGB version; it remains at sRGB.

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T03:12:05-07:00
by 4shades
oh, ok. Then my problem is that the third-party program won't accept the 16-bit sRGB, so I have to get it into RGB colorspace without darkening it.

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T03:19:12-07:00
by snibgo
Try "-set colorspace RGB". This changes metadata so it says the image is encoded as linear RGB, even though it isn't.

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T08:31:10-07:00
by 4shades
Solved - will supply details tomorrow.
Cheers,
4Shades

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T08:58:04-07:00
by glennrp
If your image is being displayed the way you like on browsers that don't do color management, you simply need to remove the color management chunks (gAMA, sRGB, cHRM, iCCP) from your PNG file. You can do this with the -strip option to IM, or you can use another PNG editor such as pngcrush to remove them. Upgrading your ImageMagick from 6.8.1 to the current version will help, as well.

Re: Image conversion 8b -> 16b without darkening

Posted: 2016-11-13T18:12:45-07:00
by 4shades
OK, here is the solution I am using.

First, it was helpful for me to realise that the source of my problems was not really the bit depth of the image, it was the color space. Moving from sRGB to RGB or Grayscale was imposing a transformation that was affecting the image histogram (making the image darker). Ultimately I need to run my image through an old third-party image processing program that requires 16-bit Grayscale images, i.e. 16 bits per pixel. But I had to go from 8-bit sRGB to 16-bit Grayscale somehow, while preserving the histogram. This requires two main steps.

1. Convert sRGB/8 to Gray/16

Code: Select all

convert im_sRGB.png -colorspace Gray -type Grayscale -depth 16 -define png:format=png16 im_Gray16.png
This gives the right color space and bit depth, but a darkened image (as rendered by the third-party program).

2. Re-build the histogram
Each pixel in the sRGB/8 image contains three bytes, one each for the red, green and blue channels. My images are all greyscale, so each of these channels has equal intensity. Therefore I can focus on, say, the red channel alone. At each pixel in the sRGB/8 image I determine the red intensity and I then apply that intensity to the corresponding pixel in the Gray/16 image. I do this programmatically using MVG scripting. For example, assuming pixel (19,19) in sRGB/8 image has red intensity 65, then I can issue the following MVG commands to set the correct gray intensity for the corresponding Gray/16 pixel:

Code: Select all

fill gray(65)
rectangle 19,19 20,20
I have to do this for each pixel in the image, which means it is most efficient to aggregate all such MVG pixel commands into a file (call it histo.mvg) and apply them all at once with a single command line execution.

Code: Select all

convert im_Gray16.png -define png:bit-depth=16 -draw @histo.mvg im_Gray16histo.png
Hey presto, I have the right colorspace, the right bit depth, the right number of bits per pixel, and the right histogram. And the third-party program reads and renders the file beautifully.

Of course, step 1 could be replaced by creating a simple blank canvas in Gray/16 format and re-constructing the image content using step 2, but it is instructive for me to do the transformation to be able to compare the before and after versions in each step.

Many thanks to all who posted with tips and advice, helping me learn and organize my thoughts.

Cheers,
4Shades