diff options
-rw-r--r-- | src/gen-image.c | 101 |
1 files changed, 44 insertions, 57 deletions
diff --git a/src/gen-image.c b/src/gen-image.c index d2d4870..2f85463 100644 --- a/src/gen-image.c +++ b/src/gen-image.c @@ -758,9 +758,37 @@ static void image_convert_rgb_to_rgb(const struct image *input, } /* RGB to YUV */ -static void csc_matrix(enum v4l2_ycbcr_encoding encoding, - enum v4l2_quantization quantization, - int (*matrix)[3][3]) +static void csc_rgb_to_yuv(const int ccm[3][3], bool full_range, + const uint8_t rgb[3], uint8_t ycbcr[3]) +{ + int y_min = full_range ? 0 : 16; + int y_max = full_range ? 255 : 235; + int cbcr_min = full_range ? 0 : 16; + int cbcr_max = full_range ? 255 : 240; + int div = 1 << 11; + int r, g, b; + int y, cb, cr; + + r = rgb[0]; + g = rgb[1]; + b = rgb[2]; + + y = (ccm[0][0] * r + ccm[0][1] * g + ccm[0][2] * b + y_min * div + div / 2) / div; + cb = (ccm[1][0] * r + ccm[1][1] * g + ccm[1][2] * b + 128 * div + div / 2) / div; + cr = (ccm[2][0] * r + ccm[2][1] * g + ccm[2][2] * b + 128 * div + div / 2) / div; + +#define CLAMP(x, low, high) \ + ((x) < (low) ? (low) : ( (x) > (high) ? (high) : (x) )) + + ycbcr[0] = CLAMP(y, y_min, y_max); + ycbcr[1] = CLAMP(cb, cbcr_min, cbcr_max); + ycbcr[2] = CLAMP(cr, cbcr_min, cbcr_max); +} + +static void image_convert_rgb_to_yuv(const struct image *input, + struct image *output, + const struct format_info *format, + const struct csc_params *params) { /* * The value of the coefficients has been reverse-engineered by @@ -802,76 +830,35 @@ static void csc_matrix(enum v4l2_ycbcr_encoding encoding, { 1047, -951, -96 }, }; - bool full = quantization == V4L2_QUANTIZATION_FULL_RANGE; - unsigned int i; - const int (*m)[3][3]; + bool full_range = params->quantization == V4L2_QUANTIZATION_FULL_RANGE; + const int (*matrix)[3][3]; + const uint8_t *idata = input->data; + uint8_t *odata = output->data; + unsigned int x; + unsigned int y; - switch (encoding) { + switch (params->encoding) { case V4L2_YCBCR_ENC_601: default: - m = full ? &bt601_full : &bt601; + matrix = full_range ? &bt601_full : &bt601; break; case V4L2_YCBCR_ENC_709: - m = full ? &rec709_full : &rec709; + matrix = full_range ? &rec709_full : &rec709; break; } - for (i = 0; i < ARRAY_SIZE(*m); ++i) - memcpy((*matrix)[i], (*m)[i], sizeof((*m)[i])); -} - -static void csc_rgb_to_yuv(int m[3][3], enum v4l2_quantization quantization, - const uint8_t rgb[3], uint8_t ycbcr[3]) -{ - bool full = quantization == V4L2_QUANTIZATION_FULL_RANGE; - int y_min = full ? 0 : 16; - int y_max = full ? 255 : 235; - int cbcr_min = full ? 0 : 16; - int cbcr_max = full ? 255 : 240; - int div = 1 << 11; - int r, g, b; - int y, cb, cr; - - r = rgb[0]; - g = rgb[1]; - b = rgb[2]; - - y = (m[0][0] * r + m[0][1] * g + m[0][2] * b + y_min * div + div / 2) / div; - cb = (m[1][0] * r + m[1][1] * g + m[1][2] * b + 128 * div + div / 2) / div; - cr = (m[2][0] * r + m[2][1] * g + m[2][2] * b + 128 * div + div / 2) / div; - -#define CLAMP(x, low, high) \ - ((x) < (low) ? (low) : ( (x) > (high) ? (high) : (x) )) - - ycbcr[0] = CLAMP(y, y_min, y_max); - ycbcr[1] = CLAMP(cb, cbcr_min, cbcr_max); - ycbcr[2] = CLAMP(cr, cbcr_min, cbcr_max); -} - -static void image_convert_rgb_to_yuv(const struct image *input, - struct image *output, - const struct format_info *format, - const struct csc_params *params) -{ - int matrix[3][3]; - const uint8_t *idata = input->data; - uint8_t *odata = output->data; - unsigned int x; - unsigned int y; - - csc_matrix(params->encoding, params->quantization, &matrix); - for (y = 0; y < output->height; ++y) { - for (x = 0; x < output->width; ++x) { - csc_rgb_to_yuv(matrix, params->quantization, + for (x = 0; x < output->width; ++x) + csc_rgb_to_yuv(*matrix, full_range, &idata[3*x], &odata[3*x]); - } + if (format->yuv.xsub == 2) { for (x = 1; x < output->width - 1; x += 2) { odata[3*x + 1] = (odata[3*(x-1) + 1] + odata[3*(x+1) + 1]) / 2; odata[3*x + 2] = (odata[3*(x-1) + 2] + odata[3*(x+1) + 2]) / 2; } } + idata += 3 * output->width; odata += 3 * output->width; } |