Skip to content

Improvements related to image dithering and low-bit-depth output #3141

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 24, 2021

Conversation

lgritz
Copy link
Collaborator

@lgritz lgritz commented Oct 20, 2021

We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

  • When the option is used, it should apply dither any time you are
    reducing an image with > 8 bits/channel to an output with <= 8
    bits/channel. Not just from float/half, but also from uint16, for
    example. (When outputting > 8 bits per channel, there are enough
    gradations that you tend not to see banding artifacts, so dithering
    is not necessary for 16 bit output, even if coming from a float data
    source.)

  • Change the actual dither we use to blue noise. The old dither just
    used a hash to add uniformly distributed random numbers to each
    pixel value before quantization, completely uncorrelated from pixel
    to pixel. Blue noise is specially constructed to still have a
    uniform distribution of the output range, but it ensures that
    spatially, similar values are distributed as far away from each
    other as possible, rather than having similar values sometimes
    clumped together. The result is a MUCH NICER appearance.

  • Of course, this means the we needed to store a blue noise table in
    the library, and some access routines for it. We incorporate a
    public domain blue noise texture as a table.

  • ImageBufAlgo::noise() and oiiotool --noise now take "blue" as a
    noise name to return blue noise. Also, make "white" the (preferred)
    synonym for "uniform" (to disambiguate the fact that both white and
    blue noise are uniformly distributed; the difference is that white
    is independently random for each pixel, whereas blue shapes the
    spectrum to favor high frequencies, making it better suited for
    dithering and sampling purposes.

  • ImageBufAlgo::bluenoise_image() returns a reference to a stored
    periodic blue noise image.

  • oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
    12 bit output (for formats that support it), but had no way to ask
    for less than 8 bit output (for example, TIFF supports that). So we
    add "uint6", "uint4", "uint2", "uint1" as recognized names for the
    -d option in those rare cases when you specifically want to
    produce a low bit depth file. And furthermore, if you ask for
    --dither when using lower bit depths, the dither amplitude is
    adjusted to be right sized for the bit depth you are using.

  • Many format output modules that support 8 bit output honor the
    option to dither the output, but in the "built-in plugins" chapter
    of the docs, most did not list this option in the section that
    describes which special output options it knows. So now we've added
    this to the docs for all the output plugins that did support it.

We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

* When the option is used, it should apply dither any time you are
  reducing an image with > 8 bits/channel to an output with <= 8
  bits/channel. Not just from float/half, but also from uint16, for
  example. (When outputting > 8 bits per channel, there are enough
  gradations that you tend not to see banding artifacts, so dithering
  is not necessary for 16 bit output, even if coming from a float data
  source.)

* Change the actual dither we use to blue noise. The old dither just
  used a hash to add uniformly distributed random numbers to each
  pixel value before quantization, completely uncorrelated from pixel
  to pixel. Blue noise is specially constructed to still have a
  uniform distribution of the output range, but it ensures that
  spatially, similar values are distributed as far away from each
  other as possible, rather than having similar values sometimes
  clumped together.  The result is a MUCH NICER appearance.

* Of course, this means the we needed to store a blue noise table in
  the library, and some access routines for it. We incorporate a
  public domain blue noise texture as a table.

* ImageBufAlgo::noise() and `oiiotool --noise` now take "blue" as a
  noise name to return blue noise. Also, make "white" the (preferred)
  synonym for "uniform" (to disambiguate the fact that both white and
  blue noise are uniformly distributed; the difference is that white
  is independently random for each pixel, whereas blue shapes the
  spectrum to favor high frequencies, making it better suited for
  dithering and sampling purposes.

* ImageBufAlgo::bluenoise_image() returns a reference to a stored
  periodic blue noise image.

* oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
  12 bit output (for formats that support it), but had no way to ask
  for less than 8 bit output (for example, TIFF supports that). So we
  add "uint6", "uint4", "uint2", "uint1" as recognized names for the
  `-d` option in those rare cases when you specifically want to
  produce a low bit depth file. And furthermore, if you ask for
  `--dither` when using lower bit depths, the dither amplitude is
  adjusted to be right sized for the bit depth you are using.

* Many format output modules that support 8 bit output honor the
  option to dither the output, but in the "built-in plugins" chapter
  of the docs, most did not list this option in the section that
  describes which special output options it knows. So now we've added
  this to the docs for all the output plugins that did support it.
@lgritz lgritz merged commit a844c7a into AcademySoftwareFoundation:master Oct 24, 2021
lgritz added a commit to lgritz/OpenImageIO that referenced this pull request Oct 24, 2021
…demySoftwareFoundation#3141)

We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

* When the option is used, it should apply dither any time you are
  reducing an image with > 8 bits/channel to an output with <= 8
  bits/channel. Not just from float/half, but also from uint16, for
  example. (When outputting > 8 bits per channel, there are enough
  gradations that you tend not to see banding artifacts, so dithering
  is not necessary for 16 bit output, even if coming from a float data
  source.)

* Change the actual dither we use to blue noise. The old dither just
  used a hash to add uniformly distributed random numbers to each
  pixel value before quantization, completely uncorrelated from pixel
  to pixel. Blue noise is specially constructed to still have a
  uniform distribution of the output range, but it ensures that
  spatially, similar values are distributed as far away from each
  other as possible, rather than having similar values sometimes
  clumped together.  The result is a MUCH NICER appearance.

* Of course, this means the we needed to store a blue noise table in
  the library, and some access routines for it. We incorporate a
  public domain blue noise texture as a table.

* ImageBufAlgo::noise() and `oiiotool --noise` now take "blue" as a
  noise name to return blue noise. Also, make "white" the (preferred)
  synonym for "uniform" (to disambiguate the fact that both white and
  blue noise are uniformly distributed; the difference is that white
  is independently random for each pixel, whereas blue shapes the
  spectrum to favor high frequencies, making it better suited for
  dithering and sampling purposes.

* ImageBufAlgo::bluenoise_image() returns a reference to a stored
  periodic blue noise image.

* oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
  12 bit output (for formats that support it), but had no way to ask
  for less than 8 bit output (for example, TIFF supports that). So we
  add "uint6", "uint4", "uint2", "uint1" as recognized names for the
  `-d` option in those rare cases when you specifically want to
  produce a low bit depth file. And furthermore, if you ask for
  `--dither` when using lower bit depths, the dither amplitude is
  adjusted to be right sized for the bit depth you are using.

* Many format output modules that support 8 bit output honor the
  option to dither the output, but in the "built-in plugins" chapter
  of the docs, most did not list this option in the section that
  describes which special output options it knows. So now we've added
  this to the docs for all the output plugins that did support it.
lgritz added a commit to lgritz/OpenImageIO that referenced this pull request Nov 7, 2021
…demySoftwareFoundation#3141)

We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

* When the option is used, it should apply dither any time you are
  reducing an image with > 8 bits/channel to an output with <= 8
  bits/channel. Not just from float/half, but also from uint16, for
  example. (When outputting > 8 bits per channel, there are enough
  gradations that you tend not to see banding artifacts, so dithering
  is not necessary for 16 bit output, even if coming from a float data
  source.)

* Change the actual dither we use to blue noise. The old dither just
  used a hash to add uniformly distributed random numbers to each
  pixel value before quantization, completely uncorrelated from pixel
  to pixel. Blue noise is specially constructed to still have a
  uniform distribution of the output range, but it ensures that
  spatially, similar values are distributed as far away from each
  other as possible, rather than having similar values sometimes
  clumped together.  The result is a MUCH NICER appearance.

* Of course, this means the we needed to store a blue noise table in
  the library, and some access routines for it. We incorporate a
  public domain blue noise texture as a table.

* ImageBufAlgo::noise() and `oiiotool --noise` now take "blue" as a
  noise name to return blue noise. Also, make "white" the (preferred)
  synonym for "uniform" (to disambiguate the fact that both white and
  blue noise are uniformly distributed; the difference is that white
  is independently random for each pixel, whereas blue shapes the
  spectrum to favor high frequencies, making it better suited for
  dithering and sampling purposes.

* ImageBufAlgo::bluenoise_image() returns a reference to a stored
  periodic blue noise image.

* oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
  12 bit output (for formats that support it), but had no way to ask
  for less than 8 bit output (for example, TIFF supports that). So we
  add "uint6", "uint4", "uint2", "uint1" as recognized names for the
  `-d` option in those rare cases when you specifically want to
  produce a low bit depth file. And furthermore, if you ask for
  `--dither` when using lower bit depths, the dither amplitude is
  adjusted to be right sized for the bit depth you are using.

* Many format output modules that support 8 bit output honor the
  option to dither the output, but in the "built-in plugins" chapter
  of the docs, most did not list this option in the section that
  describes which special output options it knows. So now we've added
  this to the docs for all the output plugins that did support it.
@lgritz lgritz deleted the lg-bluenoise branch November 8, 2021 04:02
lgritz added a commit to lgritz/OpenImageIO that referenced this pull request Nov 21, 2021
…demySoftwareFoundation#3141)

We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

* When the option is used, it should apply dither any time you are
  reducing an image with > 8 bits/channel to an output with <= 8
  bits/channel. Not just from float/half, but also from uint16, for
  example. (When outputting > 8 bits per channel, there are enough
  gradations that you tend not to see banding artifacts, so dithering
  is not necessary for 16 bit output, even if coming from a float data
  source.)

* Change the actual dither we use to blue noise. The old dither just
  used a hash to add uniformly distributed random numbers to each
  pixel value before quantization, completely uncorrelated from pixel
  to pixel. Blue noise is specially constructed to still have a
  uniform distribution of the output range, but it ensures that
  spatially, similar values are distributed as far away from each
  other as possible, rather than having similar values sometimes
  clumped together.  The result is a MUCH NICER appearance.

* Of course, this means the we needed to store a blue noise table in
  the library, and some access routines for it. We incorporate a
  public domain blue noise texture as a table.

* ImageBufAlgo::noise() and `oiiotool --noise` now take "blue" as a
  noise name to return blue noise. Also, make "white" the (preferred)
  synonym for "uniform" (to disambiguate the fact that both white and
  blue noise are uniformly distributed; the difference is that white
  is independently random for each pixel, whereas blue shapes the
  spectrum to favor high frequencies, making it better suited for
  dithering and sampling purposes.

* ImageBufAlgo::bluenoise_image() returns a reference to a stored
  periodic blue noise image.

* oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
  12 bit output (for formats that support it), but had no way to ask
  for less than 8 bit output (for example, TIFF supports that). So we
  add "uint6", "uint4", "uint2", "uint1" as recognized names for the
  `-d` option in those rare cases when you specifically want to
  produce a low bit depth file. And furthermore, if you ask for
  `--dither` when using lower bit depths, the dither amplitude is
  adjusted to be right sized for the bit depth you are using.

* Many format output modules that support 8 bit output honor the
  option to dither the output, but in the "built-in plugins" chapter
  of the docs, most did not list this option in the section that
  describes which special output options it knows. So now we've added
  this to the docs for all the output plugins that did support it.
lgritz added a commit to lgritz/OpenImageIO that referenced this pull request Nov 22, 2021
…demySoftwareFoundation#3141)

We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

* When the option is used, it should apply dither any time you are
  reducing an image with > 8 bits/channel to an output with <= 8
  bits/channel. Not just from float/half, but also from uint16, for
  example. (When outputting > 8 bits per channel, there are enough
  gradations that you tend not to see banding artifacts, so dithering
  is not necessary for 16 bit output, even if coming from a float data
  source.)

* Change the actual dither we use to blue noise. The old dither just
  used a hash to add uniformly distributed random numbers to each
  pixel value before quantization, completely uncorrelated from pixel
  to pixel. Blue noise is specially constructed to still have a
  uniform distribution of the output range, but it ensures that
  spatially, similar values are distributed as far away from each
  other as possible, rather than having similar values sometimes
  clumped together.  The result is a MUCH NICER appearance.

* Of course, this means the we needed to store a blue noise table in
  the library, and some access routines for it. We incorporate a
  public domain blue noise texture as a table.

* ImageBufAlgo::noise() and `oiiotool --noise` now take "blue" as a
  noise name to return blue noise. Also, make "white" the (preferred)
  synonym for "uniform" (to disambiguate the fact that both white and
  blue noise are uniformly distributed; the difference is that white
  is independently random for each pixel, whereas blue shapes the
  spectrum to favor high frequencies, making it better suited for
  dithering and sampling purposes.

* ImageBufAlgo::bluenoise_image() returns a reference to a stored
  periodic blue noise image.

* oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
  12 bit output (for formats that support it), but had no way to ask
  for less than 8 bit output (for example, TIFF supports that). So we
  add "uint6", "uint4", "uint2", "uint1" as recognized names for the
  `-d` option in those rare cases when you specifically want to
  produce a low bit depth file. And furthermore, if you ask for
  `--dither` when using lower bit depths, the dither amplitude is
  adjusted to be right sized for the bit depth you are using.

* Many format output modules that support 8 bit output honor the
  option to dither the output, but in the "built-in plugins" chapter
  of the docs, most did not list this option in the section that
  describes which special output options it knows. So now we've added
  this to the docs for all the output plugins that did support it.
lgritz added a commit to lgritz/OpenImageIO that referenced this pull request Nov 29, 2021
…demySoftwareFoundation#3141)

We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

* When the option is used, it should apply dither any time you are
  reducing an image with > 8 bits/channel to an output with <= 8
  bits/channel. Not just from float/half, but also from uint16, for
  example. (When outputting > 8 bits per channel, there are enough
  gradations that you tend not to see banding artifacts, so dithering
  is not necessary for 16 bit output, even if coming from a float data
  source.)

* Change the actual dither we use to blue noise. The old dither just
  used a hash to add uniformly distributed random numbers to each
  pixel value before quantization, completely uncorrelated from pixel
  to pixel. Blue noise is specially constructed to still have a
  uniform distribution of the output range, but it ensures that
  spatially, similar values are distributed as far away from each
  other as possible, rather than having similar values sometimes
  clumped together.  The result is a MUCH NICER appearance.

* Of course, this means the we needed to store a blue noise table in
  the library, and some access routines for it. We incorporate a
  public domain blue noise texture as a table.

* ImageBufAlgo::noise() and `oiiotool --noise` now take "blue" as a
  noise name to return blue noise. Also, make "white" the (preferred)
  synonym for "uniform" (to disambiguate the fact that both white and
  blue noise are uniformly distributed; the difference is that white
  is independently random for each pixel, whereas blue shapes the
  spectrum to favor high frequencies, making it better suited for
  dithering and sampling purposes.

* ImageBufAlgo::bluenoise_image() returns a reference to a stored
  periodic blue noise image.

* oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
  12 bit output (for formats that support it), but had no way to ask
  for less than 8 bit output (for example, TIFF supports that). So we
  add "uint6", "uint4", "uint2", "uint1" as recognized names for the
  `-d` option in those rare cases when you specifically want to
  produce a low bit depth file. And furthermore, if you ask for
  `--dither` when using lower bit depths, the dither amplitude is
  adjusted to be right sized for the bit depth you are using.

* Many format output modules that support 8 bit output honor the
  option to dither the output, but in the "built-in plugins" chapter
  of the docs, most did not list this option in the section that
  describes which special output options it knows. So now we've added
  this to the docs for all the output plugins that did support it.
lgritz added a commit to lgritz/OpenImageIO that referenced this pull request Nov 30, 2021
…demySoftwareFoundation#3141)

We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

* When the option is used, it should apply dither any time you are
  reducing an image with > 8 bits/channel to an output with <= 8
  bits/channel. Not just from float/half, but also from uint16, for
  example. (When outputting > 8 bits per channel, there are enough
  gradations that you tend not to see banding artifacts, so dithering
  is not necessary for 16 bit output, even if coming from a float data
  source.)

* Change the actual dither we use to blue noise. The old dither just
  used a hash to add uniformly distributed random numbers to each
  pixel value before quantization, completely uncorrelated from pixel
  to pixel. Blue noise is specially constructed to still have a
  uniform distribution of the output range, but it ensures that
  spatially, similar values are distributed as far away from each
  other as possible, rather than having similar values sometimes
  clumped together.  The result is a MUCH NICER appearance.

* Of course, this means the we needed to store a blue noise table in
  the library, and some access routines for it. We incorporate a
  public domain blue noise texture as a table.

* ImageBufAlgo::noise() and `oiiotool --noise` now take "blue" as a
  noise name to return blue noise. Also, make "white" the (preferred)
  synonym for "uniform" (to disambiguate the fact that both white and
  blue noise are uniformly distributed; the difference is that white
  is independently random for each pixel, whereas blue shapes the
  spectrum to favor high frequencies, making it better suited for
  dithering and sampling purposes.

* ImageBufAlgo::bluenoise_image() returns a reference to a stored
  periodic blue noise image.

* oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
  12 bit output (for formats that support it), but had no way to ask
  for less than 8 bit output (for example, TIFF supports that). So we
  add "uint6", "uint4", "uint2", "uint1" as recognized names for the
  `-d` option in those rare cases when you specifically want to
  produce a low bit depth file. And furthermore, if you ask for
  `--dither` when using lower bit depths, the dither amplitude is
  adjusted to be right sized for the bit depth you are using.

* Many format output modules that support 8 bit output honor the
  option to dither the output, but in the "built-in plugins" chapter
  of the docs, most did not list this option in the section that
  describes which special output options it knows. So now we've added
  this to the docs for all the output plugins that did support it.
lgritz added a commit to lgritz/OpenImageIO that referenced this pull request Dec 1, 2021
…demySoftwareFoundation#3141)

We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

* When the option is used, it should apply dither any time you are
  reducing an image with > 8 bits/channel to an output with <= 8
  bits/channel. Not just from float/half, but also from uint16, for
  example. (When outputting > 8 bits per channel, there are enough
  gradations that you tend not to see banding artifacts, so dithering
  is not necessary for 16 bit output, even if coming from a float data
  source.)

* Change the actual dither we use to blue noise. The old dither just
  used a hash to add uniformly distributed random numbers to each
  pixel value before quantization, completely uncorrelated from pixel
  to pixel. Blue noise is specially constructed to still have a
  uniform distribution of the output range, but it ensures that
  spatially, similar values are distributed as far away from each
  other as possible, rather than having similar values sometimes
  clumped together.  The result is a MUCH NICER appearance.

* Of course, this means the we needed to store a blue noise table in
  the library, and some access routines for it. We incorporate a
  public domain blue noise texture as a table.

* ImageBufAlgo::noise() and `oiiotool --noise` now take "blue" as a
  noise name to return blue noise. Also, make "white" the (preferred)
  synonym for "uniform" (to disambiguate the fact that both white and
  blue noise are uniformly distributed; the difference is that white
  is independently random for each pixel, whereas blue shapes the
  spectrum to favor high frequencies, making it better suited for
  dithering and sampling purposes.

* ImageBufAlgo::bluenoise_image() returns a reference to a stored
  periodic blue noise image.

* oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
  12 bit output (for formats that support it), but had no way to ask
  for less than 8 bit output (for example, TIFF supports that). So we
  add "uint6", "uint4", "uint2", "uint1" as recognized names for the
  `-d` option in those rare cases when you specifically want to
  produce a low bit depth file. And furthermore, if you ask for
  `--dither` when using lower bit depths, the dither amplitude is
  adjusted to be right sized for the bit depth you are using.

* Many format output modules that support 8 bit output honor the
  option to dither the output, but in the "built-in plugins" chapter
  of the docs, most did not list this option in the section that
  describes which special output options it knows. So now we've added
  this to the docs for all the output plugins that did support it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant