📄 colorspace.c
字号:
/***************************************************************************** * * XVID MPEG-4 VIDEO CODEC * - colorspace conversion module - * * Copyright(C) 2002 Peter Ross <pross@xvid.org> * 2002 Michael Militzer <isibaar@xvid.org> * * This file is part of XviD, a free MPEG-4 video encoder/decoder * * XviD is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Under section 8 of the GNU General Public License, the copyright * holders of XVID explicitly forbid distribution in the following * countries: * * - Japan * - United States of America * * Linking XviD statically or dynamically with other modules is making a * combined work based on XviD. Thus, the terms and conditions of the * GNU General Public License cover the whole combination. * * As a special exception, the copyright holders of XviD give you * permission to link XviD with independent modules that communicate with * XviD solely through the VFW1.1 and DShow interfaces, regardless of the * license terms of these independent modules, and to copy and distribute * the resulting combined work under terms of your choice, provided that * every copy of the combined work is accompanied by a complete copy of * the source code of XviD (the version of XviD used to produce the * combined work), being distributed under the terms of the GNU General * Public License plus this exception. An independent module is a module * which is not derived from or based on XviD. * * Note that people who make modified versions of XviD are not obligated * to grant this special exception for their modified versions; it is * their choice whether to do so. The GNU General Public License gives * permission to release a modified version without this exception; this * exception also makes it possible to release a modified version which * carries forward this exception. * * $Id: colorspace.c,v 1.7 2002/11/26 23:44:10 edgomez Exp $ * ****************************************************************************/#include <string.h> /* memcpy */#include "colorspace.h"#include "../divx4.h" /* DEC_PICTURE *//* function pointers *//* input */color_inputFuncPtr rgb555_to_yv12;color_inputFuncPtr rgb565_to_yv12;color_inputFuncPtr rgb24_to_yv12;color_inputFuncPtr rgb32_to_yv12;color_inputFuncPtr yuv_to_yv12;color_inputFuncPtr yuyv_to_yv12;color_inputFuncPtr uyvy_to_yv12;/* output */color_outputFuncPtr yv12_to_rgb555;color_outputFuncPtr yv12_to_rgb565;color_outputFuncPtr yv12_to_rgb24;color_outputFuncPtr yv12_to_rgb32;color_outputFuncPtr yv12_to_yuv;color_outputFuncPtr yv12_to_yuyv;color_outputFuncPtr yv12_to_uyvy;#define MIN(A,B) ((A)<(B)?(A):(B))#define MAX(A,B) ((A)>(B)?(A):(B))/* rgb -> yuv def's this following constants are "official spec" Video Demystified" (ISBN 1-878707-09-4) rgb<->yuv _is_ lossy, since most programs do the conversion differently SCALEBITS/FIX taken from ffmpeg*/#define Y_R_IN 0.257#define Y_G_IN 0.504#define Y_B_IN 0.098#define Y_ADD_IN 16#define U_R_IN 0.148#define U_G_IN 0.291#define U_B_IN 0.439#define U_ADD_IN 128#define V_R_IN 0.439#define V_G_IN 0.368#define V_B_IN 0.071#define V_ADD_IN 128#define SCALEBITS_IN 8#define FIX_IN(x) ((uint16_t) ((x) * (1L<<SCALEBITS_IN) + 0.5))int32_t RGB_Y_tab[256];int32_t B_U_tab[256];int32_t G_U_tab[256];int32_t G_V_tab[256];int32_t R_V_tab[256];/* rgb555 -> yuv 4:2:0 planar */voidrgb555_to_yv12_c(uint8_t * y_out, uint8_t * u_out, uint8_t * v_out, uint8_t * src, int width, int height, int y_stride){ int32_t src_stride = width * 2; uint32_t y_dif = y_stride - width; uint32_t uv_dif = (y_stride - width) / 2; uint32_t x, y; if (height < 0) { height = -height; src += (height - 1) * src_stride; src_stride = -src_stride; } for (y = height / 2; y; y--) { /* process one 2x2 block per iteration */ for (x = 0; x < (uint32_t) width; x += 2) { int rgb, r, g, b, r4, g4, b4; rgb = *(uint16_t *) (src + x * 2); b4 = b = (rgb << 3) & 0xf8; g4 = g = (rgb >> 2) & 0xf8; r4 = r = (rgb >> 7) & 0xf8; y_out[0] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; rgb = *(uint16_t *) (src + x * 2 + src_stride); b4 += b = (rgb << 3) & 0xf8; g4 += g = (rgb >> 2) & 0xf8; r4 += r = (rgb >> 7) & 0xf8; y_out[y_stride] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; rgb = *(uint16_t *) (src + x * 2 + 2); b4 += b = (rgb << 3) & 0xf8; g4 += g = (rgb >> 2) & 0xf8; r4 += r = (rgb >> 7) & 0xf8; y_out[1] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; rgb = *(uint16_t *) (src + x * 2 + src_stride + 2); b4 += b = (rgb << 3) & 0xf8; g4 += g = (rgb >> 2) & 0xf8; r4 += r = (rgb >> 7) & 0xf8; y_out[y_stride + 1] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; *u_out++ = (uint8_t) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 + FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + U_ADD_IN; *v_out++ = (uint8_t) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 - FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + V_ADD_IN; y_out += 2; } src += src_stride * 2; y_out += y_dif + y_stride; u_out += uv_dif; v_out += uv_dif; }}/* rgb565_to_yuv_c NOTE: identical to rgb555 except for shift/mask not tested */voidrgb565_to_yv12_c(uint8_t * y_out, uint8_t * u_out, uint8_t * v_out, uint8_t * src, int width, int height, int y_stride){ int32_t src_stride = width * 2; uint32_t y_dif = y_stride - width; uint32_t uv_dif = (y_stride - width) / 2; uint32_t x, y; if (height < 0) { height = -height; src += (height - 1) * src_stride; src_stride = -src_stride; } for (y = height / 2; y; y--) { /* process one 2x2 block per iteration */ for (x = 0; x < (uint32_t) width; x += 2) { int rgb, r, g, b, r4, g4, b4; rgb = *(uint16_t *) (src + x * 2); b4 = b = (rgb << 3) & 0xf8; g4 = g = (rgb >> 3) & 0xfc; r4 = r = (rgb >> 8) & 0xf8; y_out[0] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; rgb = *(uint16_t *) (src + x * 2 + src_stride); b4 += b = (rgb << 3) & 0xf8; g4 += g = (rgb >> 3) & 0xfc; r4 += r = (rgb >> 8) & 0xf8; y_out[y_stride] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; rgb = *(uint16_t *) (src + x * 2 + 2); b4 += b = (rgb << 3) & 0xf8; g4 += g = (rgb >> 3) & 0xfc; r4 += r = (rgb >> 8) & 0xf8; y_out[1] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; rgb = *(uint16_t *) (src + x * 2 + src_stride + 2); b4 += b = (rgb << 3) & 0xf8; g4 += g = (rgb >> 3) & 0xfc; r4 += r = (rgb >> 8) & 0xf8; y_out[y_stride + 1] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; *u_out++ = (uint8_t) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 + FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + U_ADD_IN; *v_out++ = (uint8_t) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 - FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + V_ADD_IN; y_out += 2; } src += src_stride * 2; y_out += y_dif + y_stride; u_out += uv_dif; v_out += uv_dif; }}/* rgb24 -> yuv 4:2:0 planar NOTE: always flips.*/voidrgb24_to_yv12_c(uint8_t * y_out, uint8_t * u_out, uint8_t * v_out, uint8_t * src, int width, int height, int stride){ uint32_t width3 = (width << 1) + width; /* width * 3 */ uint32_t src_dif = (width << 3) + width; /* width3 * 3 */ uint32_t y_dif = (stride << 1) - width; uint32_t uv_dif = (stride - width) >> 1; uint32_t x, y; src += (height - 2) * width3; for (y = height >> 1; y; y--) { for (x = width >> 1; x; x--) { uint32_t r, g, b, r4, g4, b4; b4 = b = src[0]; g4 = g = src[1]; r4 = r = src[2]; y_out[stride + 0] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; b4 += (b = src[3]); g4 += (g = src[4]); r4 += (r = src[5]); y_out[stride + 1] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; b4 += (b = src[width3 + 0]); g4 += (g = src[width3 + 1]); r4 += (r = src[width3 + 2]); y_out[0] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; b4 += (b = src[width3 + 3]); g4 += (g = src[width3 + 4]); r4 += (r = src[width3 + 5]); y_out[1] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; *u_out++ = (uint8_t) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 + FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + U_ADD_IN; *v_out++ = (uint8_t) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 - FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + V_ADD_IN; src += 6; y_out += 2; } src -= src_dif; y_out += y_dif; u_out += uv_dif; v_out += uv_dif; }}/* rgb32 -> yuv 4:2:0 planar NOTE: always flips*/voidrgb32_to_yv12_c(uint8_t * y_out, uint8_t * u_out, uint8_t * v_out, uint8_t * src, int width, int height, int stride){ uint32_t width4 = (width << 2); /* width * 4 */ uint32_t src_dif = 3 * width4; uint32_t y_dif = (stride << 1) - width; uint32_t uv_dif = (stride - width) >> 1; uint32_t x, y; src += (height - 2) * width4; for (y = height >> 1; y; y--) { for (x = width >> 1; x; x--) { uint32_t r, g, b, r4, g4, b4; b4 = b = src[0]; g4 = g = src[1]; r4 = r = src[2]; y_out[stride + 0] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; b4 += (b = src[4]); g4 += (g = src[5]); r4 += (r = src[6]); y_out[stride + 1] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; b4 += (b = src[width4 + 0]); g4 += (g = src[width4 + 1]); r4 += (r = src[width4 + 2]); y_out[0] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; b4 += (b = src[width4 + 4]); g4 += (g = src[width4 + 5]); r4 += (r = src[width4 + 6]); y_out[1] = (uint8_t) ((FIX_IN(Y_R_IN) * r + FIX_IN(Y_G_IN) * g + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; *u_out++ = (uint8_t) ((-FIX_IN(U_R_IN) * r4 - FIX_IN(U_G_IN) * g4 + FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + U_ADD_IN; *v_out++ = (uint8_t) ((FIX_IN(V_R_IN) * r4 - FIX_IN(V_G_IN) * g4 - FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + V_ADD_IN; src += 8; y_out += 2; } src -= src_dif; y_out += y_dif; u_out += uv_dif; v_out += uv_dif; }}/* yuv planar -> yuv 4:2:0 planar NOTE: does not flip */voidyuv_to_yv12_c(uint8_t * y_out, uint8_t * u_out, uint8_t * v_out, uint8_t * src, int width, int height, int stride){ uint32_t stride2 = stride >> 1; uint32_t width2 = width >> 1; uint32_t y; for (y = height; y; y--) { memcpy(y_out, src, width); src += width; y_out += stride; } for (y = height >> 1; y; y--) { memcpy(u_out, src, width2); src += width2; u_out += stride2; } for (y = height >> 1; y; y--) { memcpy(v_out, src, width2); src += width2; v_out += stride2; }}/* yuyv (yuv2) packed -> yuv 4:2:0 planar NOTE: does not flip */voidyuyv_to_yv12_c(uint8_t * y_out, uint8_t * u_out, uint8_t * v_out, uint8_t * src, int width, int height, int stride){ uint32_t width2 = width + width; uint32_t y_dif = stride - width; uint32_t uv_dif = y_dif >> 1; uint32_t x, y; for (y = height >> 1; y; y--) { for (x = width >> 1; x; x--) { *y_out++ = *src++; /**u_out++ = *src++; */ *u_out++ = (*(src + width2) + *src) >> 1; src++; *y_out++ = *src++; /**v_out++ = *src++; */ *v_out++ = (*(src + width2) + *src) >> 1; src++; } y_out += y_dif; u_out += uv_dif; v_out += uv_dif; for (x = width >> 1; x; x--) { *y_out++ = *src++; src++; *y_out++ = *src++; src++; } y_out += y_dif; }}/* uyvy packed -> yuv 4:2:0 planar NOTE: does not flip */voiduyvy_to_yv12_c(uint8_t * y_out, uint8_t * u_out, uint8_t * v_out, uint8_t * src, int width, int height, int stride){ uint32_t width2 = width + width; uint32_t y_dif = stride - width; uint32_t uv_dif = y_dif >> 1; uint32_t x, y; for (y = height >> 1; y; y--) { for (x = width >> 1; x; x--) { *u_out++ = *src++; /* *u_out++ = (*(src+width2) + *src++) >> 1; */ *y_out++ = *src++; /**v_out++ = *src++; */ *v_out++ = (*(src + width2) + *src) >> 1; src++; *y_out++ = *src++; } y_out += y_dif; u_out += uv_dif;; v_out += uv_dif;; for (x = width >> 1; x; x--) { src++; *y_out++ = *src++; src++; *y_out++ = *src++; } y_out += y_dif; }}/* yuv -> rgb def's */#define RGB_Y_OUT 1.164#define B_U_OUT 2.018#define Y_ADD_OUT 16#define G_U_OUT 0.391#define G_V_OUT 0.813#define U_ADD_OUT 128#define R_V_OUT 1.596#define V_ADD_OUT 128#define SCALEBITS_OUT 13
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -