Page 1 of 1

Controlled dithering, 16-bit to 8-bit

Posted: 2017-07-26T01:56:24-07:00
by cda
Hello.
I am having trouble understanding dithering. In short: I want to be able to do whatever it is Photoshop does when switching color depth (per channel) from 16-bit to 8-bit mode. The overall aim is to batch-convert normalmaps and heightmaps to an appropriate format.

To keep it simple I'm trying to convert a linear black-to-white 4k 16-bit gradient to 256 colors. I'm expecting to see no banding when zoomed in on the output. So far my only successful attempts are with ordered dithering:

magick in.tiff -ordered-dither o8x8,256 out.tiff
Which is mostly what I want, except that I'd prefer to have no discernable pattern, which I assume is what all the other dithering methods are for.

magick in.tiff out.gif
From the documentation I got the impression that default settings already should give me the result I want. This produces a gradient with undithered 16-pixel-thick bands instead.

magick in.tiff -depth 8 out.tiff
magick in.tiff -dither FloydSteinberg -depth 8 out.tiff

Same banding.

magick in.tiff -colors 255 out.tiff
magick in.tiff -dither Riemersma -colors 255 out.tiff
magick in.tiff -dither FloydSteinberg -colors 255 out.tiff

The above dithers the way I want it to, except all the way down to 64 colors.

magick in.tiff -remap out.gif out.tiff
This again dithers to 64 colors despite out.gif containing 256 colors. Tried with a 255-color palette file as well, same result. I might be misunderstanding palettes. And in general, I feel like I'm either missing something obvious or don't understand something fundamental.


(Using IM 7.0.6-3 Q16 x64 2017-07-24 / Win7)

Re: Controlled dithering, 16-bit to 8-bit

Posted: 2017-07-26T07:59:47-07:00
by snibgo
On "-colors", see http://www.imagemagick.org/script/comma ... php#colors :
The actual number of colors in the image may be less than your request, but never more.
The more regular the input, the more likely that a colour-reduction will give you fewer than you asked for.

"-depth 8" just drops precision with no dithering. (If the input has 16 bits/channel, it drops bits by dividing by 257.)

"-remap" using a map of grayscale gradient with 256 colours, and no dithering, gives an output with 256 colours, as I would expect. But dithering with "-remap" gives only 64 colours, as you say, and I don't know why.

One solution is to do your own random dithering, by adding noise, then a simple "-depth 8". Windows syntax:

Code: Select all

magick ^
 -size 100x4096 gradient: g.tiff

magick ^
 -size 1x256 gradient: m.tiff

magick ^
  g.tiff ^
  -remap m.tiff ^
  +write g2.tiff ^
  -unique-colors info:

magick ^
  g.tiff ^
  +noise Uniform ^
  -depth 8 ^
  +write g3.tiff ^
  -unique-colors info:
g3.tiff has 256 colours, with random dithering.

Re: Controlled dithering, 16-bit to 8-bit

Posted: 2017-07-26T15:07:26-07:00
by cda
Thanks.
magick in.tiff -attenuate 0.25 +noise Uniform -depth 8 out.tiff
This was the effect I was looking for.

Although, I'd be interested to know how much of a difference a proper dithering algorithm would theoretically make on something other than a basic gradient. Am I correct in thinking that it would be trying to preserve the finer details? Or is this more or less as good as it gets for a 16-bit to 8-bit conversion?

Re: Controlled dithering, 16-bit to 8-bit

Posted: 2017-07-26T15:35:34-07:00
by snibgo
Proper dithering distributes the error from one pixel to influence the next, so this loses less information than a random dither.

However, as a final image, I personally prefer the random dither. The high precision is lost with both methods, but patterning caused by error-distributing dither can be too distracting.

Re: Controlled dithering, 16-bit to 8-bit

Posted: 2017-07-26T16:36:20-07:00
by cda
Okay, thanks again.

Re: Controlled dithering, 16-bit to 8-bit

Posted: 2017-07-27T05:10:41-07:00
by glennrp
Also try "-random-threshold" which is essentially a 1x1 dither (i.e., no dithering)

Re: Controlled dithering, 16-bit to 8-bit

Posted: 2017-07-27T08:02:17-07:00
by cda
Sorry, you'll have to expand on that. Say, "-random-threshold 0x100%" on a grayscale input gives me a monochrome dithered image. I can't see how I'd use this to get a 256-color image.

Re: Controlled dithering, 16-bit to 8-bit

Posted: 2017-07-28T17:27:16-07:00
by glennrp
Right, "random-threshold" reduces the image to black and white pixels. I think there's a way to random-dither each channel to get an 8-color image. But no way to get a 256-color image with it.