High-quality reduction of HDR images to 24-bit color

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
iSKUNK!

High-quality reduction of HDR images to 24-bit color

Post by iSKUNK! »

I have an HDR image (in EXR format) that I'd like to convert to an 8-bit/channel PNG with as little loss of apparent quality as possible. Most notably, I want to do this with an E-dither to avoid posterization artifacts. (Clamping channels to the [0, 1] range is a given.)

How would I do this in IM? If you do convert in.exr -depth 24 out.png then the colors are simply truncated (i.e. lower bits dropped), so you get posterization. Adding -dither to that does nothing.

(By the way, I'm using this as a test image. It's an extremely subtle vertical gradient.)

I also tried -posterize 256, which seemed like it might do what I want. However, if you examine the resulting image, you see that adjacent pixels have fairly large differences between them; e.g. (127,127,127) and (134,134,134) might be horizontal neighbors. Meaning that the reduction is not optimal.

Is there perhaps a different approach to this that I've missed?
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: High-quality reduction of HDR images to 24-bit color

Post by magick »

When you built ImageMagick did you add --enable-hdri to your configure script? That may help otherwise HDRI support if new to ImageMagick and we are looking for advice on tweaking existing algorithms or developing new algorithms to better support the HDRI community.
iSKUNK!

Re: High-quality reduction of HDR images to 24-bit color

Post by iSKUNK! »

Ah yes, I should have noted:
Version: ImageMagick 6.3.5 07/09/07 Q32 HDRI http://www.imagemagick.org
Copyright: Copyright (C) 1999-2007 ImageMagick Studio LLC
This is a custom build I'm using, from the SVN source.

FWIW, the most intuitive approach would be something like convert in.exr -depth 24 -dither out.png, where the -depth operator can make use of dithering in the general case of downsampling.

Is there a more roundabout way to get this effect with things as they are, or would new code really be needed?
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: High-quality reduction of HDR images to 24-bit color

Post by magick »

Does this command not give you the expected results:
  • convert grey-gradient.exr.bin +matte -depth 8 image.png
iSKUNK!

Re: High-quality reduction of HDR images to 24-bit color

Post by iSKUNK! »

Afraid not. That truncates the colors.

Here is the image converted with +matte: grey-gradient-matte.png

And here is the image, dithered with a custom-written Floyd-Steinberg filter: grey-gradient-fsdither.png

If you load them both into an image editor, and expand the color range with the Levels tool, you'll see clear banding in the first, and a gradual dither in the second. Horizontally adjacent pixels in the second image differ in intensity by 1/255 at most, so the dither is as good as it can get. That's what I'm after.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: High-quality reduction of HDR images to 24-bit color

Post by magick »

With a patch to ImageMagick 6.3.5-1 Beta we get reasonable results with this command:
  • convert grey-gradient.exr.bin -treedepth 8 -colors 256 -depth 8 grey-gradient-hilbertdither.png
Dithering on a Hilbert curve gives a different distribution of error than Floyd-Steinberg so it may not be what you want.
iSKUNK!

Re: High-quality reduction of HDR images to 24-bit color

Post by iSKUNK! »

The SVN build is currently broken, so I can't try that out.

As I understand, however, -colors 256 means that the output image will use no more (and possibly less) than 256 unique colors. Which works for the gradient test image, but the goal is to reduce arbitrary HDR images to 24-bit PNG files, not 8-bit paletted GIFs. Essentially, it would be like -colors 16777216---except that you wouldn't want to waste time building up an optimal color set of that size.

The error distribution isn't an issue, as long as it's not patterned. The whole trick is in treating the 24-bit color space as the "palette," and dithering accordingly. You're not so much reducing the number of colors in the image, as much as rounding each floating-point channel to the nearest 1/255 step and distributing the errors of that.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: High-quality reduction of HDR images to 24-bit color

Post by magick »

We understand how FS-dithering works and it probably does a good job distributing error, however, it seems that the proper way to convert HDR images to 8 or 16-bits per channel is with tonal mapping. If you have an algorithm available for proper tonal mapping, post it here. Otherwise we will need to research this topic a bit more and come up with a good tonal map to solve this problem.
iSKUNK!

Re: High-quality reduction of HDR images to 24-bit color

Post by iSKUNK! »

I think I probably goofed in using the term "HDR" here. I'm working with floating-point images that have already been clamped to [0, 1], so tonal mapping isn't an issue. (Or, to be more precise, my scenario comes after the mapping has been applied.) It's just a straightforward matter of quantization.

As far as code goes, this is as much magic as should be needed:

Code: Select all

px_quant.r = floorf(N_LEVELS * px->r + 0.5) / N_LEVELS;
px_quant.g = floorf(N_LEVELS * px->g + 0.5) / N_LEVELS;
px_quant.b = floorf(N_LEVELS * px->b + 0.5) / N_LEVELS;
px_quant.a = floorf(N_LEVELS * px->a + 0.5) / N_LEVELS;
where N_LEVELS is either 255.0 or 65535.0.

(I agree on the need for tonal mapping in converting arbitrary HDR images to 8- or 16-bit format, but that would be done in a preceding stage of a convert(1) pipeline. That is to say, it's an orthogonal problem.)
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: High-quality reduction of HDR images to 24-bit color

Post by magick »

ImageMagick 6.3.5-1 return results with a slightly different formulation with this command (see SetImageDepth()):
  • convert grey-gradient.exr.bin -depth 8 +matte grey-gradient
After normalizing you still get the banding though because no error diffusion has been applied.
iSKUNK!

Re: High-quality reduction of HDR images to 24-bit color

Post by iSKUNK! »

Huh, so -depth is basically handled by SetImageChannelDepth(), I see. The RoundToQuantum() lines look familiar.

Would it be feasible to enable -dither to work in conjunction with -depth? What I'm after basically boils down to that, and the color-reducing behavior of -depth (when given an appropriate argument) presents a general situation where you may want to resort to dithering. It's applicable outside of HDR images, and even outside of floating-point images: consider the case of reducing 16 bits/channel images to 8.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: High-quality reduction of HDR images to 24-bit color

Post by magick »

We have already considered dithering the error in SetImageDepth(). However, SetImageDepth() is a core method and any change could affect a large number of existing workflows. A proper solution will require deep-thought and extensive testing before we could release it.
iSKUNK!

Re: High-quality reduction of HDR images to 24-bit color

Post by iSKUNK! »

Well, the dithering would occur only if explicitly requested via -dither, wouldn't it? Otherwise, the behavior would remain as now, banding and all. I don't see that there's a need to have -depth dither by default when converting downward, unless the goal is to actually change the default, to make banding a less common result.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: High-quality reduction of HDR images to 24-bit color

Post by magick »

Dithering is enabled by default. It still would require a bit of work to determine if the dither option was explicitly set as well as enabling the dithering option when setting the image depth. We'll add it to our list of things to do.
iSKUNK!

Re: High-quality reduction of HDR images to 24-bit color

Post by iSKUNK! »

I understand the difficulty now.

Kind thanks for your patience in this thread, and for taking an interest in the problem. I look forward to making good use of error-diffused depth reduction once it becomes available in IM, and hope others will find it beneficial as well.
Post Reply