Controlled dithering, 16-bit to 8-bit

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?".
Post Reply
cda
Posts: 4
Joined: 2017-07-26T01:45:08-07:00
Authentication code: 1151

Controlled dithering, 16-bit to 8-bit

Post by cda » 2017-07-26T01:56:24-07:00

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)

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

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

Post by snibgo » 2017-07-26T07:59:47-07:00

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.
snibgo's IM pages: im.snibgo.com

cda
Posts: 4
Joined: 2017-07-26T01:45:08-07:00
Authentication code: 1151

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

Post by cda » 2017-07-26T15:07:26-07:00

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?

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

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

Post by snibgo » 2017-07-26T15:35:34-07:00

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.
snibgo's IM pages: im.snibgo.com

cda
Posts: 4
Joined: 2017-07-26T01:45:08-07:00
Authentication code: 1151

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

Post by cda » 2017-07-26T16:36:20-07:00

Okay, thanks again.

User avatar
glennrp
Posts: 1147
Joined: 2006-04-01T08:16:32-07:00
Location: Maryland 39.26.30N 76.16.01W

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

Post by glennrp » 2017-07-27T05:10:41-07:00

Also try "-random-threshold" which is essentially a 1x1 dither (i.e., no dithering)

cda
Posts: 4
Joined: 2017-07-26T01:45:08-07:00
Authentication code: 1151

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

Post by cda » 2017-07-27T08:02:17-07:00

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.

User avatar
glennrp
Posts: 1147
Joined: 2006-04-01T08:16:32-07:00
Location: Maryland 39.26.30N 76.16.01W

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

Post by glennrp » 2017-07-28T17:27:16-07:00

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.

Post Reply