Use TV range algorithm for bit-depth conversions
authorAnton Mitrofanov <BugMaster@narod.ru>
Sun, 22 Jan 2012 18:13:52 +0000 (22:13 +0400)
committerJason Garrett-Glaser <jason@x264.com>
Sat, 4 Feb 2012 15:18:16 +0000 (07:18 -0800)
Such sources are more common, so better to be correct for the common case.
This also produces less error for the case of full range than the previous algorithm produced for the case of TV range.

filters/video/depth.c
input/raw.c

index 43b84db..e01aaae 100644 (file)
@@ -65,12 +65,12 @@ static int csp_num_interleaved( int csp, int plane )
  * depth again is lossless. */
 #define DITHER_PLANE( pitch ) \
 static void dither_plane_##pitch( pixel *dst, int dst_stride, uint16_t *src, int src_stride, \
-                                        int width, int height, int16_t *errors ) \
+                                  int width, int height, int16_t *errors ) \
 { \
     const int lshift = 16-BIT_DEPTH; \
-    const int rshift = 2*BIT_DEPTH-16; \
+    const int rshift = 16-BIT_DEPTH+2; \
+    const int half = 1 << (16-BIT_DEPTH+1); \
     const int pixel_max = (1 << BIT_DEPTH)-1; \
-    const int half = 1 << (16-BIT_DEPTH); \
     memset( errors, 0, (width+1) * sizeof(int16_t) ); \
     for( int y = 0; y < height; y++, src += src_stride, dst += dst_stride ) \
     { \
@@ -78,8 +78,8 @@ static void dither_plane_##pitch( pixel *dst, int dst_stride, uint16_t *src, int
         for( int x = 0; x < width; x++ ) \
         { \
             err = err*2 + errors[x] + errors[x+1]; \
-            dst[x*pitch] = x264_clip3( (((src[x*pitch]+half)<<2)+err)*pixel_max >> 18, 0, pixel_max ); \
-            errors[x] = err = src[x*pitch] - (dst[x*pitch] << lshift) - (dst[x*pitch] >> rshift); \
+            dst[x*pitch] = x264_clip3( ((src[x*pitch]<<2)+err+half) >> rshift, 0, pixel_max ); \
+            errors[x] = err = src[x*pitch] - (dst[x*pitch] << lshift); \
         } \
     } \
 }
@@ -114,13 +114,8 @@ static void dither_image( cli_image_t *out, cli_image_t *img, int16_t *error_buf
 
 static void scale_image( cli_image_t *output, cli_image_t *img )
 {
-    /* this function mimics how swscale does upconversion. 8-bit is converted
-     * to 16-bit through left shifting the orginal value with 8 and then adding
-     * the original value to that. This effectively keeps the full color range
-     * while also being fast. for n-bit we basically do the same thing, but we
-     * discard the lower 16-n bits. */
     int csp_mask = img->csp & X264_CSP_MASK;
-    const int shift = 16-BIT_DEPTH;
+    const int shift = BIT_DEPTH - 8;
     for( int i = 0; i < img->planes; i++ )
     {
         uint8_t *src = img->plane[i];
@@ -131,7 +126,7 @@ static void scale_image( cli_image_t *output, cli_image_t *img )
         for( int j = 0; j < height; j++ )
         {
             for( int k = 0; k < width; k++ )
-                dst[k] = ((src[k] << 8) + src[k]) >> shift;
+                dst[k] = src[k] << shift;
 
             src += img->stride[i];
             dst += output->stride[i]/2;
index 53a9ca2..a9b2de1 100644 (file)
@@ -113,9 +113,8 @@ static int read_frame_internal( cli_pic_t *pic, raw_hnd_t *h )
             uint16_t *plane = (uint16_t*)pic->img.plane[i];
             uint64_t pixel_count = h->plane_size[i];
             int lshift = 16 - h->bit_depth;
-            int rshift = 2*h->bit_depth - 16;
             for( uint64_t j = 0; j < pixel_count; j++ )
-                plane[j] = (plane[j] << lshift) + (plane[j] >> rshift);
+                plane[j] = plane[j] << lshift;
         }
     }
     return error;