📄 colorspace.c
字号:
/************************************************************************** * * XVID MPEG-4 VIDEO CODEC * colorspace conversions * * This program is an implementation of a part of one or more MPEG-4 * Video tools as specified in ISO/IEC 14496-2 standard. Those intending * to use this software module in hardware or software products are * advised that its use may infringe existing patents or copyrights, and * any such use would be at such party's own risk. The original * developer of this software module and his/her company, and subsequent * editors and their companies, will have no liability for use of this * software or modifications or derivatives thereof. * * This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. * *************************************************************************//************************************************************************** * * History: * * 30.02.2002 out_yuv dst_stride2 fix * 26.02.2002 rgb555, rgb565 * 24.11.2001 accuracy improvement to yuyv/vyuy conversion * 28.10.2001 total rewrite <pross@cs.rmit.edu.au> * **************************************************************************/#include <string.h> // memcpy#include "colorspace.h"// 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;#ifndef MIN#define MIN(A,B) ((A)<(B)?(A):(B))#define MAX(A,B) ((A)>(B)?(A):(B))#endif/* 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 */void rgb555_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 */void rgb565_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.*/void rgb24_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*/void rgb32_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 */void yuv_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; }}#ifdef MPEG4IPvoid yuv_to_yv12_clip_c(uint8_t *y_out, uint8_t *u_out, uint8_t *v_out, uint8_t *src, int width, int height, int raw_height, int stride){ uint32_t stride2 = stride >> 1; uint32_t width2 = width >> 1; uint32_t y; uint32_t yoffset = ((raw_height - height) / 2) * width; src += yoffset; for (y = height; y; y--) { memcpy(y_out, src, width); src += width; y_out += stride; } src += yoffset + (yoffset / 4); for (y = height >> 1; y; y--) { memcpy(u_out, src, width2); src += width2; u_out += stride2; } src += yoffset / 2; for (y = height >> 1; y; y--) { memcpy(v_out, src, width2); src += width2; v_out+= stride2; }}#endif/* yuyv (yuv2) packed -> yuv 4:2:0 planar NOTE: does not flip */void yuyv_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 */void uyvy_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++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -