On Thu, 2011-08-25 at 08:36 +0200, madshi wrote: > > The current code in swscale is based on how 8-bit to > > 16-bit YUV conversions have been done earlier - basically > > duplicating each input byte in the output (e.g. 0xf0 -> 0xf0f0, > > 0x65 -> 0x6565). I believe this is the right thing for full > > range content. > > Not necessarily. If you upscale like that, smooth gradiants > will not be perfectly smooth, anymore.
Gradients are perfectly smooth for a 8->16 conversion like that. You seem to be assuming the special case of a 8->10 conversion done by shifting out the lowest bits of the 16-bit value again. > IMHO, there are three > ways to upscale full range content: > > (1) 10bit = 8bit << 2 > (2) 10bit = round(8bit * 1023 / 255) (similar to byte duplicating) > (3) 10bit = dither(8bit * 1023 / 255) > > Solution (1) keeps gradiants smooth, but loses a bit of > dynamic range. Solution (2) maintains full dynamic range, > but gradiants are not perfectly smooth, anymore. Solution > (3) keep gradiants smooth *and* maintains full dynamic > range. However, if you try to compress (3), compression > efficiency will go down due to the dither noise. Also (3) will > perform slowest, of course. > > My personal favorites are either (1) or (3), while swscale > currently does (2). swscale does no "/ 255" stuff AFAIK. If "byte duplication" is used that's multiplication by 257; corresponding 8->10 conversion would be multiplication by 257/64, not 1023/255 (these won't produce exactly the same results even if the former is rounded down and the latter to nearest). > Furthermore, the chroma channel needs to be scaled > with signed math, to make sure that 8bit 128 gets properly > scaled to 10bit 512. If you use (1), though, signed math > is not necessary. By "signed math" I assume you mean something like C*(x-128)+512 instead of what you wrote in (2)/(3) (at least that would be the most correct way - implementing it does not actually require using signed arithmetic though). But note that different chroma ranges actually have different _shapes_ in the sense that the "neutral point" is a different portion of the range away from the absolute middle of the range (it's always +0.5 absolute units off from the middle, but that's a smaller portion of the range for larger ranges). No value of C in the above will produce exactly the full dynamic range from 0 to 1023: if you make C large enough to produce 1023 at the top end then the bottom will be below 0 already. _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
