View Full Version : Animate dithering from 8-bit to 1-bit?
Reel.Deel
1st December 2014, 18:43
Hi,
I came across this video that illustrates Floyd–Steinberg dithering from 8 to 1-bit. It seems like it was done in AviSynth so I was wondering how it was done.
Here's the reference video (FFV1): Floyd-steinberg dither 8 to 1 bit.avi (nmm.me/f6)
feisty2
2nd December 2014, 03:15
You can scale down 8bits to 1bit by "smoothcurve", but don't know if it uses Floyd Steinberg dithering
feisty2
2nd December 2014, 03:17
Why do you want 1bit anyway, I dont think anyone can really stand that kind of poor quality
Reel.Deel
2nd December 2014, 03:43
I just think it's a nifty illustration and I'm interested in how it's done in avs, that's all.
feisty2
2nd December 2014, 04:00
edit: forget it, I was outta my mind, it's wrong
pandy
2nd December 2014, 13:50
Why do you want 1bit anyway, I dont think anyone can really stand that kind of poor quality
You need significantly higher resolution then quality will be OK.
Side to this seem that dither is overloaded and for 1 bit incorrect result are produced.
Hi,
I came across this video that illustrates Floyd–Steinberg dithering from 8 to 1-bit. It seems like it was done in AviSynth so I was wondering how it was done.
Not necessarily - perhaps VDub was used (with plugin http://whitewing.co.uk/vdub_errdiff.html ) - did some checking and for 1 bit result from Mike filter are significantly better - dither is not overloaded.
feisty2
2nd December 2014, 13:56
You need significantly higher resolution then quality will be OK.
Side to this seem that dither is overloaded and for 1 bit incorrect result are produced.
1bit will never be okay to most natural images (color images) even with ultra high resolution, cuz you only get grayscale image at 1bit, you need at least 3bits to store color images (1bit for each color channel)
pandy
2nd December 2014, 14:18
1bit will never be okay to most natural images (color images) even with ultra high resolution, cuz you only get grayscale image at 1bit, you need at least 3bits to store color images (1bit for each color channel)
1 bit per component x by component channels = bits per pixel
feisty2
2nd December 2014, 14:28
1 bit per component x by component channels = bits per pixel
yeah, you wouldn't call 1bpc 1bit unless its grayscale
when we say "bit", I think it's commonly accepted as bpp
edit: typos
feisty2
2nd December 2014, 14:34
like the famous "True Color" (RGB24, or 24bits RGB) = 8bits for each channel x 3 channels
or "yv12", it's 8bits for plane Y and 2bits (should be 8bits but actually only takes 2bits due to the chroma subsample) for plane U and V = 12bits in total, so "yv12"
Mounir
2nd December 2014, 19:29
?#*!? yv12 is 4.2.0 that's 6 bits to me
Wilbert
2nd December 2014, 19:41
?#*!? yv12 is 4.2.0 that's 6 bits to me
It's 12 bit (hence the name :)). Chroma is shared between four pixels. So for four pixels we have: 4x8 bits (luma) + 2x8 (UV) = 48 bit. Hence 48/4 = 12 bit per pixel.
poisondeathray
2nd December 2014, 22:21
Is reason you thought of avisynth the "bit depth" overlay looks like subtitle() ? :D
Couldn't this have been done with an image editor like gimp and put together in avisynth with imagesource() ?
cretindesalpes
3rd December 2014, 13:44
This is not a problem at 8 bits, but when dithering to a very low bitdepth, you have to use linear-light pixel values (for the error diffusion) and quantification levels from the final colorspace, otherwise you’ll get wrong perceived colors and light levels. Unfortunately, available tools for Avisynth don’t offer this possibility.
feisty2
3rd December 2014, 16:19
This is not a problem at 8 bits, but when dithering to a very low bitdepth, you have to use linear-light pixel values (for the error diffusion) and quantification levels from the final colorspace, otherwise you’ll get wrong perceived colors and light levels. Unfortunately, available tools for Avisynth don’t offer this possibility.
16bpc to 1bit
dither_y_gamma_to_linear (tv_range_in=false,tv_range_out=false)
expr="0-0;65535-1"
SmoothCurve16 (Ycurve=expr, mode=0, interp=0, HQ=True, dither=75, limiter=False, TVrange=0)
dither_get_lsb ()
mt_lut ("x 255 *")
grayscale ()
feisty2
3rd December 2014, 16:28
honestly, 1bit looks like nothing but shit to me
colours
3rd December 2014, 16:38
BlankClip(length=8, width=256, height=256, pixel_type="y8", fps=1, color_yuv=$800000)
r=mt_lutspa(mode="absolute",expr="x")
g=mt_lutspa(mode="absolute",expr="y")
b=mt_lutspa(mode="absolute",expr="255 x -")
mergergb(r,g,b)
pointresize(512,512)
function reduce(clip c,int depth)
{
assert(depth>=1&&depth<=8,"depth must be between 1 and 8 (inclusive)")
assert(c.isrgb(),"clip must be RGB")
if(depth==8){return c}
r=c.showred("y8")
g=c.showgreen("y8")
b=c.showblue("y8")
interleave(r,g,b)
dither_convert_8_to_16()
dither_y_gamma_to_linear(tv_range_in=false,tv_range_out=false)
dither_lut16("x 2 "+string(depth)+" ^ 1 - * 255 / round")
converttoyv12().dither_add_grain16(var=0.005).converttoy8()
f3kdb_dither(mode=1)
dither_lut8("x 2 "+string(depth)+" ^ 1 - / 255 * 256 * round")
dither_y_linear_to_gamma(tv_range_in=false,tv_range_out=false)
f3kdb_dither()
mergergb(selectevery(3,0),selectevery(3,1),selectevery(3,2))
}
scriptclip("""depth=8-current_frame
reduce(depth).subtitle("bit depth: "+string(depth))""")
pandy
3rd December 2014, 17:19
I would say that with VDub filter (mentioned previously) results are satisfactory (dither seem to be not overloaded).
Not sure how it is implemented internally but i believe that with sufficiently high resolution it provide results comparable to higher bit depths.
@cretindesalpes - any chance to add a_dither to next release of "dither"? http://pippin.gimp.org/a_dither/
feisty2
4th December 2014, 05:14
i believe that with sufficiently high resolution it provide results comparable to higher bit depths.
like I mentioned earlier, it's only true when >=3bits (1 bpc), otherwise you can't store color images
edit: stupid typo yet again
pandy
4th December 2014, 15:55
like I mentioned earlier, it's only true when >=3bits (1 bpp), otherwise you can't store color images
Once again - seem that it is obvious... we talking about quantization levels not how many bits per pixel.
feisty2
4th December 2014, 16:07
Once again - seem that it is obvious... we talking about quantization levels not how many bits per pixel.
okay, you may upscale a common 8bpc image then shrink its domain to 1bpc then downsize it to its original resolution, and see how much you gotta upscale to make the result acceptable :D
I believe it's gonna be a fun experiment
feisty2
4th December 2014, 16:22
my guess would be around 11.314 (8*sqt (2)) times the original resolution
reason: (sqt (2^8/2^1))
colours
4th December 2014, 18:08
There's the simple and crude lower bound of a scaling factor of √8, simply by considering the amount of information.
If you allow specifying the downscaling filter, then by choosing a box filter for that purpose, it's easy to exactly reconstruct the 8-bpc image with a scaling factor of 16. (This is most easily accomplished by also using a box filter for upscaling (i.e. nearest neighbour) and using a 16×16 ordered dither when downconverting to 1 bpc.)
If you instead assume that the upscaling and downscaling filters are both sincs, and that the quantisation error is proportional to 2^(-depth) and behaves exactly like white noise, for a scaling factor of n, applying the downscaling filter would reduce the energy of the quantisation error by a factor of n². Since the energy is the square of the standard deviation of the quantisation error, what we want is for √(n²) = 2^(-1)/2^(-8), i.e. a scaling factor of n = 128 (both horizontally and vertically).
Of course, this analysis is too basic to be entirely accurate: with one-bit signals, there's simply no "room" for the quantisation error to behave anything like white noise, and for that matter, quantisation error is ideally not like white noise (given that noise shaping is A Thing That Exists). Taking everything into account makes this seemingly innocent question very nontrivial to answer from a theoretical perspective.
pandy
5th December 2014, 20:04
okay, you may upscale a common 8bpc image then shrink its domain to 1bpc then downsize it to its original resolution, and see how much you gotta upscale to make the result acceptable :D
I believe it's gonna be a fun experiment
http://caca.zoy.org/study/part4.html
extreme case
http://en.wikipedia.org/wiki/Oversampled_binary_image_sensor
Reel.Deel
15th December 2014, 15:57
@colours
Thanks for the script, very cool how you guys just come up this stuff. I've been away from my home computer so had not had a chance to try it.
@pandy
a_dither seems interesting. Every know and then I do cinemagraphs and a few regular GIFs here and there. I wish Avisynth had ways to optimize GIFs...
pandy
18th December 2014, 12:04
@pandy
a_dither seems interesting. Every know and then I do cinemagraphs and a few regular GIFs here and there. I wish Avisynth had ways to optimize GIFs...
a_dtiher looks to me as a good candidate to survive lossy compression with not significant reduction of quality (should consume significantly less bitrate than FS or noise like dither).
Yep, i agree - that's why i use ffmpeg and image magick - not fast but work nicely. GIF are still OK - few days ago i use animated gif to show some problem on 2.4GHz spectrum.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.