[v1.104] JPEG decoding with dithering

XnConvert Multi Platform - Windows, MacOSX, Linux

Moderator: xnview

User avatar
XnTriq
Forum Librarian
Posts: 6563
Joined: Sun Sep 25, 2005 3:00 am
Location: Ref Desk

[v1.104] JPEG decoding with dithering

Post by XnTriq »

  1. Go to SettingsLoad format settings…Read.
  2. Set DCT to Floating.
  3. Set Dithering to None.
  4. Convert a JPEG to PNG.
  5. Repeat the conversion with Dithering = Ordered.
  6. Repeat the conversion with Dithering = Floyd-Steinberg.
The resulting PNGs are identical :bug:
Xn User
Posts: 283
Joined: Sat Jan 05, 2019 1:16 pm

Re: [v1.104] JPEG decoding with dithering

Post by Xn User »

Which method compression in JPEG file was be used ? This very need for report , I mean what 1x1 1x1 1x1 or 1x2 1x1 1x1 or 2x2 1x1 1x1 )
And test was be do with classic JPEG compression methods or JPEG LI compression methods ?
User avatar
XnTriq
Forum Librarian
Posts: 6563
Joined: Sun Sep 25, 2005 3:00 am
Location: Ref Desk

Re: [v1.104] JPEG decoding with dithering

Post by XnTriq »

testorig.jpg
Encoder: libjpeg
Chroma subsampling: 4:2:0 (2×2,1×1,1×1)
You do not have the required permissions to view the files attached to this post.
User avatar
xnview
Author of XnView
Posts: 47953
Joined: Mon Oct 13, 2003 7:31 am
Location: France

Re: [v1.104] JPEG decoding with dithering

Post by xnview »

XnTriq wrote: Mon Mar 10, 2025 2:30 am testorig.jpg
Encoder: libjpeg
Chroma subsampling: 4:2:0 (2×2,1×1,1×1)
if i check the code of libjpeg, it seems that dithering is only used when quantize with colormap :(
Pierre.
Xn User
Posts: 283
Joined: Sat Jan 05, 2019 1:16 pm

Re: [v1.104] JPEG decoding with dithering

Post by Xn User »

Right , Dithering must be do use only for 1x2 1x1 1x1 or 2x1 1x1 1x1 or 2x2 1x1 1x1 , for 1x1 1x1 1x1 dithering not need use )
I also asked in JPEGLi https://github.com/libjxl/libjxl/issues/4146 , you can see what XnView MP and ACDSee Pro 5.0 with IDE_ACDstd 5.0.56.0000 reading file with differ , in result XnView MP with Floyd-Steinberg colors a little rude if compare with ACDSee Pro , I see rude gradients
Xn User
Posts: 283
Joined: Sat Jan 05, 2019 1:16 pm

Re: [v1.104] JPEG decoding with dithering

Post by Xn User »

Please , add all this algorithms https://surma.dev/things/ditherpunk/ and will be learn which is better
In the end will better if this algoritms will be apply optionaly to all lossy or images with less colors
this for testing methods of dithering https://surma.dev/lab/ditherpunk/lab.html
User avatar
XnTriq
Forum Librarian
Posts: 6563
Joined: Sun Sep 25, 2005 3:00 am
Location: Ref Desk

Re: [v1.104] JPEG decoding with dithering

Post by XnTriq »

User avatar
user0
XnThusiast
Posts: 3025
Joined: Sat May 09, 2015 9:37 am

Re: [v1.104] JPEG decoding with dithering

Post by user0 »

xnview wrote: Mon Mar 10, 2025 7:20 am if i check the code of libjpeg, it seems that dithering is only used when quantize with colormap :(
yep,
  • Color quantization [legacy feature]
    is an optional post-decoding step that maps full-color pixel data to a limited palette
    • Dithering [legacy feature]
      is an optional component of color quantization that introduces structured noise to mask quantization errors, reduce visible artifacts such as banding and improve perceived color transitions
since these steps are not applicable when rendering 24/32/48-bit images, the following should be removed:
- Dithering combobox in Settings>Formats>Read - JPEG
- -dither fs switch when lib is used internally


Some details

Doc
it is clearly written in documentation:
"Note that these switches (-dither) have no effect unless color quantization is being done."
  • DJPEG DETAILS section of usage.txt in libjpeg-turbo / libjpeg

    Code: Select all

            -colors N       Reduce image to at most N colors [legacy feature].
            or -quantize N  This reduces the number of colors used in the output
                            image so that it can be stored in a colormapped file
                            format.  This feature cannot be used when decompressing
                            lossless JPEG images.  (-colors is the recommended
                            name.  -quantize is provided only for backward
                            compatibility.)
    
            -dither fs      Use Floyd-Steinberg dithering when quantizing colors
                            [legacy feature].
            -dither ordered Use ordered dithering when quantizing colors [legacy
                            feature].
            -dither none    Do not use dithering when quantizing colors [legacy
                            feature].  By default, Floyd-Steinberg dithering is
                            applied when quantizing colors.  This is slower but
                            usually produces the best results.  Ordered dithering
                            is a compromise between speed and quality.  No
                            dithering is faster but usually looks awful.  Note that
                            these switches have no effect unless color quantization
                            is being done.  Ordered dithering is only available in
                            -onepass mode.
    

Code
dither_mode is ignored if quantize_colors is false
StepCode FileAction
Parsing djpeg.c captures -dither and -colors flags
Master Control jdmaster.c sees quantize_colors == TRUE; enables the quantizer
Processing jquant*.c checks cinfo->dither_mode to decide which math loop to run (1or2 pass)
Output wr*.c writes the dithered, low-color pixels to a BMP/GIF/PPM file


Test
  1. get libjpeg-turbo binary
  2. decode JPEG
    • default output

      Code: Select all

      djpeg.exe -bmp -outfile test_0.bmp test.jpg
      Note: by default the following applied as well:
      -dct int
      chroma fancy upsampling
    • add dithering (w/o -colors N switch)

      Code: Select all

      djpeg.exe -bmp -dither fs -outfile test_1_dither_fs.bmp test.jpg
  3. compare output BMPs, they will be identical


Extra
  • Chroma subsampling
    JPEG decoders perform chroma upsampling during YCbCr-to-RGB conversion for all subsampled formats except 4:4:4
    • libjpeg-turbo (jdsample.c) uses the following:
      • fancy chroma upsampling (default)
        eg h2v1_fancy_upsample function for 4:2:2
        https://github.com/libjpeg-turbo/libjpeg-turbo/blob/main/src/jdsample.c#L281-L292 wrote: * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
        *
        * The upsampling algorithm is linear interpolation between component centers,
        * also known as a "triangle filter". This is a good compromise between speed
        * and visual quality. The centers of the output components are 1/4 and 3/4 of
        * the way between input component centers.
        *
        * A note about the "bias" calculations: when rounding fractional values to
        * integer, we do not want to always round 0.5 up to the next integer.
        * If we did that, we'd introduce a noticeable bias towards larger values.
        * Instead, this code is arranged so that 0.5 will be rounded up or down at
        * alternate pixel locations (a simple ordered dither pattern).
        Note: ordered dithering is used for numerical rounding compensation, not perceptual noise shaping.
        More sophisticated dithering algorithms provide little to no visual benefit here, because interpolation errors are already extremely small, while those algorithms would significantly increase computational cost and reduce SIMD efficiency.

  • Post-processing deblocking
    Baseline JPEG encodes images using independently quantized 8x8 DCT blocks and lacks a built-in in-loop deblocking filter (unlike newer codecs),
    which results in visible blocking artifacts, especially at higher compression ratios.

    Unfortunately, there is no single 'best' solution to mitigate format's limitations.
    Various approaches exist, from relatively simple and blurry to more restorative*, but it is always a compromise between speed/quality and out of scope of default JPEG decoding.
    *guided/bilateral filters, non-local means (including BM3D-class methods), GPU shader-based smoothing and AI restoration

  • Jpegli
    It is worth noting that the same JPEG file can yield slightly better visual quality when decoded by Jpegli compared to traditional decoders, because the JPEG standard does not strictly dictate the exact mathematical decoding process.
    Settings - read - JPEG - add Jpegli decoder


ps: hope this is enough to discourage this ignorant behavior