Log in

View Full Version : Dithered colorspace conversion?


High Speed Dubb
12th November 2002, 06:14
I’m just curious whether it has already been implemented. In other words, rather than convert the real YUY2 value to RGB32 (for example), how about adding (Uniform[0,1] - 0.5) to each component before conversion, and using random rounding afterward?

I think that would reduce color conversion problems somewhat — Well, except for the speed penalty, which would be worse. ;)

SansGrip
12th November 2002, 06:20
I think that would reduce color conversion problems somewhat — Well, except for the speed penalty, which would be worse. ;)

No price is too great for increased randomness! :D

But seriously, this sounds interesting. You probably wouldn't want to do it when converting back and forth (e.g. around a stone-age filter) but would likely work well at the end of the script. Rather akin, I think, to 24-bit audio being dithered whilst downsampled for CD mastering.

Code it up and see! ;)

High Speed Dubb
12th November 2002, 07:13
I was actually thinking pretty much in terms of fossil filters. The idea is to avoid banding/posterization from something like convert->process->convert. Of course, you’d still want to do that as little as possible.

I’m not really sure how to write it — How can a filter return a different color format than it accepts? Time for me to check the source code...

SansGrip
12th November 2002, 07:28
I was actually thinking pretty much in terms of fossil filters. The idea is to avoid banding/posterization from something like convert->process->convert.

I suppose this could be argued both ways. Wouldn't dithering increase loss in this kind of use?

I’m not really sure how to write it — How can a filter return a different color format than it accepts?

I'm guessing with very dark magic ;).

High Speed Dubb
12th November 2002, 07:42
Well, dithering should usually make the expected resulting color closer to what you would get without the colorspace conversions. But the variance would definitely be higher. In this case I think it’s worth putting up with extra variance (i.e., noise) to avoid a consistent error (generally leading to loss of color resolution and banding).

SansGrip
12th November 2002, 07:45
Well, dithering should usually make the expected resulting color closer to what you would get without the colorspace conversions. But the variance would definitely be higher.

Sounds like this could be a worthwhile addition. I'd be particularly interested since I have to convert to RGB for TMPGEnc...

sh0dan
12th November 2002, 09:54
Are you thinking about doing rounding like this:

(pixels-->)
0101010101010 for even frames
1010101010101 for odd frames?

Well - it would lead to offset errors, when I think about it. The rounding occurs with subpixel precision (IE. 15 bits ints being rounded to nearest 8 bit int).

It could be done as:

if (framenum&1) {
pixel[0] = (result[0]+32768+16384)>>16;
pixel[1] = (result[1]+32768-16384)>>16;
} else {
pixel[0] = (result[0]+32768-16384)>>16;
pixel[1] = (result[1]+32768+16384)>>16;
}


This would make pixels that are close to the rounded value round to that, and pixels close to where is rounds become dithered.

scmccarthy
12th November 2002, 12:24
High Speed Dub:

>I’m not really sure how to write it — How can a filter return a >different color format than it accepts? Time for me to check the >source code...


I just posted a small filter that converts from YV12 to YUY2. It is very easy to see how I changed the pixel type since it is only about a computer screenful long. Check it out.

High Speed Dubb
13th November 2002, 01:26
Sh0dan,
I was thinking of a pseudorandom approach, something likepixel = (result[0]+Random()*32768)>>16;But an ordered dither would certainly be faster.

scmccarthy,
Cool! Thanks for posting the code — That should let even me figure out how to do it. (But I won’t have a chance to try until at least the weekend.)

sh0dan
13th November 2002, 08:32
For a simple random generator:

static int _seed=1;

int rand(void) // Returns random number in range 0-32767
{
return ((__seed=0x41c64e6d*__seed+0x3039)>>8)&0x7FFF;
}

// OR

__asm {
mov eax,[seed]
mul eax,0x41c64e6d
add eax,0x3039
mov [seed],eax
shr eax,10
and eax,0x7fff
}

MMX equivalent of the random routine is also possible.