⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 color.cpp

📁 Window Mobile Capture with DirectDraw
💻 CPP
字号:
/*-
 * Copyright (C) 2002
 *  Robert Jiang(XIAOHUA JIANG). All rights reserved.
 * All or some portions of this file are derived from material lisenced
 * to Robert Jiang(XIAOHUA JIANG).
 */

#include "color.h"
#include "memory.h"

#define MAXSAMPLE	255
#define CENTERSAMPLE	128

/* YCbCr is defined per ITU-R BT601.5, Cb, Cr are normalized to 0...
 * MAXSAMPLE
 *      Y  =  219/255 * (0.29900 * R + 0.58700 * G + 0.11400 * B) + 16
 *      Cb = 224/255 * (-0.16874 * R - 0.33126 * G + 0.50000 * B) + CENTERJSAMPLE
 *      Cr =  224/255 * (0.50000 * R - 0.41869 * G - 0.08131 * B) + CENTERJSAMPLE
 * To avoid floating-point arithmetic, we represent the fractional constants
 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
 * the products by 2^16, with appropriate rounding, to get the correct answer.
 */
#define SCALEBITS	16
#define Y_OFFSET	((int32_t) 16L << SCALEBITS)
#define CBCR_OFFSET     ((int32_t) CENTERSAMPLE << SCALEBITS)
#define FIX(x)		((int32_t)((x)*(1L<<SCALEBITS)+0.5))
#define ONE_HALF        ((int32_t) 1 << (SCALEBITS-1))

#define R_Y_OFF         0                       /* offset to R => Y section */
#define G_Y_OFF         (1*(MAXSAMPLE+1))      /* offset to G => Y section */
#define B_Y_OFF         (2*(MAXSAMPLE+1))      /* etc. */
#define R_CB_OFF        (3*(MAXSAMPLE+1))
#define G_CB_OFF        (4*(MAXSAMPLE+1))
#define B_CB_OFF        (5*(MAXSAMPLE+1))
#define R_CR_OFF        B_CB_OFF                /* B=>Cb, R=>Cr are the same */
#define G_CR_OFF        (6*(MAXSAMPLE+1))
#define B_CR_OFF        (7*(MAXSAMPLE+1))
#define TABLE_SIZE      (8*(MAXSAMPLE+1))

#define RGB_RED		0
#define RGB_GREEN	1
#define RGB_BLUE	2
#define RGB_PIXEL_SIZE	4
#define GET_COMPONENT(x, c)	((int)(x)[(c)])

void
rgb_ycc_init(struct color_cvt *ccvt, ChromFormat chrom, int width, int height, int bpp)
{
	int i;

	ccvt->chrom_format = chrom;
	if (chrom != CHROM_444) {
		ccvt->buffer = (sample_t*)xmalloc(sizeof(sample_t)*width*height*2);
	}
	ccvt->table = (int32_t*)xmalloc(sizeof(int32_t)*TABLE_SIZE);
	ccvt->width = width; ccvt->height = height;
	for (i = 0; i <= MAXSAMPLE; i++) {
		ccvt->table[i+R_Y_OFF] = FIX(0.29900*219.0/255.0) * i;
		ccvt->table[i+G_Y_OFF] = FIX(0.58700*219.0/255.0) * i;
		ccvt->table[i+B_Y_OFF] = FIX(0.11400*219.0/255.0) * i + ONE_HALF + Y_OFFSET;
		ccvt->table[i+R_CB_OFF] = (-FIX(0.16874*224.0/255.0)) * i;
		ccvt->table[i+G_CB_OFF] = (-FIX(0.33126*224.0/255.0)) * i;
		/* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
		 * This ensures that the maximum output will round to MAXJSAMPLE
		 * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
		 */
		ccvt->table[i+B_CB_OFF] = FIX(0.50000*224.0/255.0) * i + CBCR_OFFSET + ONE_HALF - 1;
		/* B=>Cb and R=>Cr tables are the same
		 */
		ccvt->table[i+G_CR_OFF] = (-FIX(0.41869*224.0/255.0)) * i;
		ccvt->table[i+B_CR_OFF] = (-FIX(0.08131*224.0/255.0)) * i;
	}
	ccvt->pixel_size = bpp >> 3;
}

void
rgb_ycc_free(struct color_cvt *ccvt)
{
	if (ccvt->buffer != NULL)
		xfree(ccvt->buffer);
	if (ccvt->table != NULL)
		xfree(ccvt->table);
}

#define CLIP(x) ((x)<0 ? 0 : ((x)>255 ? 255 : (x)))

void
rgb_ycc_convert(const struct color_cvt *ccvt,		/* Initialised color converter */
		const sample_t *in, sample_t *out	/* Input RGB and output YCC */
		)
{
	register int r, g, b;
	register int32_t *tab = ccvt->table;
	register int x, y, w, h;
	register sample_t *y_ptr, *cb_ptr, *cr_ptr;
	register sample_t *cb_ptr_444, *cr_ptr_444;
	const sample_t *src_ptr, *p;
	sample_t *y_ptr_orig, *cb_ptr_444_orig, *cr_ptr_444_orig;
	int32_t pict_size, rgb_line_size;

	w = ccvt->width; h = ccvt->height;
	pict_size = w*h;
	rgb_line_size = ccvt->pixel_size*w;

	y_ptr = out;
	cr_ptr = y_ptr + pict_size;
	if (ccvt->chrom_format == CHROM_420) {
		cb_ptr = cr_ptr + (pict_size>>2);
		cr_ptr_444 = ccvt->buffer;
		cb_ptr_444 = cr_ptr_444 + pict_size;
	} else if (ccvt->chrom_format == CHROM_422) {
		cb_ptr = cr_ptr + (pict_size>>1);
		cr_ptr_444 = ccvt->buffer;
		cb_ptr_444 = cr_ptr_444 + pict_size;
	} else if (ccvt->chrom_format == CHROM_MONO) {
		cb_ptr = cr_ptr + (pict_size>>1);
		cr_ptr_444 = ccvt->buffer;
		cb_ptr_444 = cr_ptr_444 + pict_size;
	} else {
		cb_ptr = cr_ptr + pict_size;
		cb_ptr_444 = cb_ptr;
		cr_ptr_444 = cr_ptr;
	}

	y_ptr_orig = y_ptr;
	cr_ptr_444_orig = cr_ptr_444;
	cb_ptr_444_orig = cb_ptr_444;

	//src_ptr = in + rgb_line_size*(h-1);
	src_ptr = in;
	/* Convert RGB to YCbCr 4:4:4 firstly */
	for (y = 0; y < h; y++) {
		p = src_ptr;
		for (x = 0; x < w; x++) {
			r = GET_COMPONENT(p,RGB_RED);
			g = GET_COMPONENT(p,RGB_GREEN);
			b = GET_COMPONENT(p,RGB_BLUE);

			y_ptr[x] = (sample_t)//CLIP
				((tab[r+R_Y_OFF] + tab[g+G_Y_OFF] + tab[b+B_Y_OFF]) >> SCALEBITS);
			cr_ptr_444[x] = (sample_t)//CLIP
				((tab[r+R_CR_OFF] + tab[g+G_CR_OFF] + tab[b+B_CR_OFF]) >> SCALEBITS);
			cb_ptr_444[x] = (sample_t)//CLIP
				((tab[r+R_CB_OFF] + tab[g+G_CB_OFF] + tab[b+B_CB_OFF]) >> SCALEBITS);
			p += ccvt->pixel_size;
		}
		//src_ptr -= rgb_line_size;
		src_ptr += rgb_line_size;
		y_ptr += w; cb_ptr_444 += w; cr_ptr_444 += w;
	}

	/* Convert 4:4:4 to 4:2:0 or 4:2:2 */
	if (ccvt->chrom_format == CHROM_420) {
		for (y = 0; y < h; y += 2) {
			for (x = 0; x < w; x += 2) {
				*cr_ptr++ = cr_ptr_444_orig[x];
				*cb_ptr++ = cb_ptr_444_orig[x];
			}
			cr_ptr_444_orig += 2*w;
			cb_ptr_444_orig += 2*w;
		}
	} else if (ccvt->chrom_format == CHROM_422) {
		for (y = 0; y < h; y++) {
			for (x = 0; x < w; x += 2) {
				*cr_ptr++ = cr_ptr_444_orig[x];
				*cb_ptr++ = cb_ptr_444_orig[x];
			}
			cb_ptr_444_orig += w;
			cr_ptr_444_orig += w;
		}
	}
}


/* YCbCr is defined per ITU-R BT601.5, Cb, Cr are normalized to 0...
 * MAXSAMPLE
 *      R  = (255/219) * (Y - 16) + 255/224 * 1.40200 * (Cr - 128)
 *      G  = (255/219) * (Y - 16) - 255/224 * 0.34414 * (Cb - 128) - 255/224 * 0.71414 * (Cr - 128)
 *      B  = (255/219) * (Y - 16) + 255/224 * 1.77200 * (Cb - 128)
 */

#define Y_BASE_OFF	0
#define Cr_R_OFF	(1*(MAXSAMPLE+1))
#define Cb_G_OFF	(2*(MAXSAMPLE+1))
#define Cr_G_OFF	(3*(MAXSAMPLE+1))
#define Cb_B_OFF	(4*(MAXSAMPLE+1))
#define YCC_RGB_TABLE_SIZE	5*(MAXSAMPLE + 1)

#define RGB_CLIP(x) (ccvt->buffer[(x)+128])

void
ycc_rgb_init(struct color_cvt *ccvt, ChromFormat chrom, int width, int height, int bpp)
{
	int i;

	ccvt->chrom_format = chrom;
	ccvt->width = width;
	ccvt->height = height;
	ccvt->table = (int32_t*)xmalloc(sizeof(int32_t)*YCC_RGB_TABLE_SIZE);
	ccvt->buffer = (sample_t*)xmalloc(sizeof(sample_t) * 512);
	for (i = 0; i < MAXSAMPLE; i++) {
		ccvt->table[Y_BASE_OFF+i] = (i - 16) * FIX(255.0/219.0) + ONE_HALF;
		ccvt->table[Cr_R_OFF+i] = (i - 128) * FIX(1.40200*255.0/224.0);
		ccvt->table[Cb_G_OFF+i] = - (i - 128) * FIX(0.34414*255.0/224.0);
		ccvt->table[Cr_G_OFF+i] = - (i - 128) * FIX(0.71414*255.0/224.0);
		ccvt->table[Cb_B_OFF+i] = (i - 128) * FIX(1.77200*255.0/224.0);
	}

	/* Initialise clip table */
	for (i = -128; i < 384; i++) {
		ccvt->buffer[i+128] = (sample_t)(i<0 ? 0 : ( i>255 ? 255 : i));
	}
	ccvt->pixel_size = bpp >> 3;
}

void
ycc_rgb_free(struct color_cvt *ccvt)
{
	if (ccvt->table != NULL)
		xfree(ccvt->table);
	if (ccvt->buffer != NULL)
		xfree(ccvt->buffer);
}

void
ycc_rgb_convert(const struct color_cvt *ccvt,
		const sample_t *in, sample_t *out
		)
{
	register int i, j;
	const register sample_t *y_ptr, *cr_ptr, *cb_ptr;
	int w, h, wc;
	int32_t y, cr, cb, r, g, b;
	int32_t pict_size, rgb_line_size;
	register sample_t *out_ptr, *p;
	const register sample_t *pcr, *pcb;

	w = ccvt->width; h = ccvt->height;
	wc = w >> (ccvt->chrom_format != CHROM_444);
	pict_size = w * h;
	rgb_line_size = ccvt->pixel_size * w;

	y_ptr = in;
	cr_ptr = y_ptr + pict_size;
	cb_ptr = cr_ptr + wc *
		(h >> (ccvt->chrom_format == CHROM_420));
	//out_ptr = out + rgb_line_size * (h-1);
	out_ptr = out;
	for (j = 0; j < h; j++) {
		p = out_ptr;
		pcr = cr_ptr;
		pcb = cb_ptr;
		for (i = 0; i < w; i++) {
			y = *y_ptr++;
			cb = *pcr; /* xiaqz:> 交换 cr, cb ? */
			cr = *pcb; 
			r = ((ccvt->table[Y_BASE_OFF+y] + ccvt->table[Cr_R_OFF+cr]) >> SCALEBITS);
			g = ((ccvt->table[Y_BASE_OFF+y]+ccvt->table[Cb_G_OFF+cb]+ccvt->table[Cr_G_OFF+cr])>>SCALEBITS);
			b = ((ccvt->table[Y_BASE_OFF+y] + ccvt->table[Cb_B_OFF+cb]) >> SCALEBITS);
			p[0] = (sample_t)RGB_CLIP(r);
			p[1] = (sample_t)RGB_CLIP(g);
			p[2] = (sample_t)RGB_CLIP(b);
			p += ccvt->pixel_size;
			pcr += i & 0x1;
			pcb += i & 0x1;
		}
		cr_ptr += wc & (0 - (j & 0x1));
		cb_ptr += wc & (0 - (j & 0x1));
		//out_ptr -= rgb_line_size;
		out_ptr += rgb_line_size;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -