STM32 tjpgd软件JPEG解码后RGB888数据格式问题

在STM32上面使用TJPGD解码后,发现RGB888的数据格式与单片机或常规的RGB格式顺序有区别,测试发现格式为BGR888,因此对源码进行了修改。

在头文件中增加一个宏定义,可以选择

#define JD_FORMAT_SWAP_RB	1	//将RGB888数据的R与B进行交换,由于原始输出的数据,R在低字节,转换为RGB888实际格式是BGR(LSB)

//定义一个24bit RGB格式结构体

//24BIT图像数据结构体
#ifdef WIN32
#pragma pack (1)		//强制使用字节对齐
typedef  struct	//__packed:让结构体的各个元素紧挨着存储
#else //MDK
typedef  __packed  struct
#endif //WIM32
{
	uint8_t mR;
	uint8_t mG;
	uint8_t mB;
}JD_RGB_24BIT;
#ifdef WIN32
#pragma pack() //取消自定义字节对齐方式。

//修改的代码主要在static JRESULT mcu_output ()内

static JRESULT mcu_output (
	JDEC* jd,		/* Pointer to the decompressor object */
	uint16_t (*outfunc)(JDEC*, void*, JRECT*),	/* RGB output function */
	uint16_t x,		/* MCU position in the image (left of the MCU) */
	uint16_t y		/* MCU position in the image (top of the MCU) */
)
{
	const int16_t CVACC = (sizeof (int16_t) > 2) ? 1024 : 128;
	uint16_t ix, iy, mx, my, rx, ry;
	int16_t yy, cb, cr;
	uint8_t* py, * pc;// *rgb24;
	JD_RGB_24BIT* pRGB24;

	JRECT rect;


	mx = jd->msx * 8; my = jd->msy * 8;					/* MCU size (pixel) */
	rx = (x + mx <= jd->width) ? mx : jd->width - x;	/* Output rectangular size (it may be clipped at right/bottom end) */
	ry = (y + my <= jd->height) ? my : jd->height - y;
	if (JD_USE_SCALE) {
		rx >>= jd->scale; ry >>= jd->scale;
		if (!rx || !ry) return JDR_OK;					/* Skip this MCU if all pixel is to be rounded off */
		x >>= jd->scale; y >>= jd->scale;
	}
	rect.left = x; rect.right = x + rx - 1;				/* Rectangular area in the frame buffer */
	rect.top = y; rect.bottom = y + ry - 1;

	
	if (!JD_USE_SCALE || jd->scale != 3) 
	{	/* Not for 1/8 scaling 没开启缩放,或者缩放大于1/8 */

		/* Build an RGB MCU from discrete comopnents */
		pRGB24 = (JD_RGB_24BIT*)jd->workbuf;
		for (iy = 0; iy < my; iy++) {
			pc = jd->mcubuf;
			py = pc + iy * 8;
			if (my == 16) {		/* Double block height? */
				pc += 64 * 4 + (iy >> 1) * 8;
				if (iy >= 8) py += 64;
			} else {			/* Single block height */
				pc += mx * 8 + iy * 8;
			}
			for (ix = 0; ix < mx; ix++) {
				cb = pc[0] - 128; 	/* Get Cb/Cr component and restore right level */
				cr = pc[64] - 128;
				if (mx == 16) {					/* Double block width? */
					if (ix == 8) py += 64 - 8;	/* Jump to next block if double block heigt */
					pc += ix & 1;				/* Increase chroma pointer every two pixels */
				} else {						/* Single block width */
					pc++;						/* Increase chroma pointer every pixel */
				}
				yy = *py++;			/* Get Y component */

				/* Convert YCbCr to RGB */

#if(JD_FORMAT_SWAP_RB)	//使能RB交换,变为RGB格式
				pRGB24->mB = /* R */ BYTECLIP(yy + ((int16_t)(1.402f * CVACC) * cr) / CVACC);
				pRGB24->mG = /* G */ BYTECLIP(yy - ((int16_t)(0.344f * CVACC) * cb + (int16_t)(0.714f * CVACC) * cr) / CVACC);
				pRGB24->mR = /* B */ BYTECLIP(yy + ((int16_t)(1.772f * CVACC) * cb) / CVACC);
				
#else //默认的BGR格式
                pRGB24->mR = /* R */ BYTECLIP(yy + ((int16_t)(1.402f * CVACC) * cr) / CVACC);
                pRGB24->mG = /* G */ BYTECLIP(yy - ((int16_t)(0.344f * CVACC) * cb + (int16_t)(0.714f * CVACC) * cr) / CVACC);
                pRGB24->mB = /* B */ BYTECLIP(yy + ((int16_t)(1.772f * CVACC) * cb) / CVACC);
#endif //JD_FORMAT_SWAP_RB	
				pRGB24++;
			}
		}

		/* Descale the MCU rectangular if needed */
		if (JD_USE_SCALE && jd->scale) {
			uint16_t x, y, r, g, b, s, w, a;
			uint8_t *op;

			/* Get averaged RGB value of each square correcponds to a pixel */
			s = jd->scale * 2;	/* Bumber of shifts for averaging */
			w = 1 << jd->scale;	/* Width of square */
			//a = (mx - w) * 3;	/* Bytes to skip for next line in the square */
			a = (mx - w);		//此处a不用乘以3,因为自定义的指针自增一次就会+3
			op = (uint8_t*)jd->workbuf;
			for (iy = 0; iy < my; iy += w) {
				for (ix = 0; ix < mx; ix += w) {
					pRGB24 = (JD_RGB_24BIT*)jd->workbuf + (iy * mx + ix);// *3;//此处a不用乘以3,因为自定义的指针自增一次就会+3
					r = g = b = 0;
					for (y = 0; y < w; y++) {	/* Accumulate RGB value in the square */
						for (x = 0; x < w; x++) 
						{
                            r += pRGB24->mR;
                            g += pRGB24->mG;
                            b += pRGB24->mB;
							pRGB24++;
						}
						pRGB24 += a;
					}							/* Put the averaged RGB value as a pixel */
					*op++ = (uint8_t)(r >> s);
					*op++ = (uint8_t)(g >> s);
					*op++ = (uint8_t)(b >> s);
				}
			}
		}

	} 
	else 
	{	/* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */

		/* Build a 1/8 descaled RGB MCU from discrete comopnents */
		pRGB24 = (JD_RGB_24BIT*)jd->workbuf;
		pc = jd->mcubuf + mx * my;
		cb = pc[0] - 128;		/* Get Cb/Cr component and restore right level */
		cr = pc[64] - 128;
		for (iy = 0; iy < my; iy += 8) {
			py = jd->mcubuf;
			if (iy == 8) py += 64 * 2;
			for (ix = 0; ix < mx; ix += 8) {
				yy = *py;	/* Get Y component */
				py += 64;

#if(JD_FORMAT_SWAP_RB)	//使能RB交换,变为RGB格式
				pRGB24->mB = /* R */ BYTECLIP(yy + ((int16_t)(1.402f * CVACC) * cr / CVACC));
                pRGB24->mG = /* G */ BYTECLIP(yy - ((int16_t)(0.344f * CVACC) * cb + (int16_t)(0.714f * CVACC) * cr) / CVACC);
                pRGB24->mR = /* B */ BYTECLIP(yy + ((int16_t)(1.772f * CVACC) * cb / CVACC));
               
#else //默认的BGR格式
                pRGB24->mR = /* R */ BYTECLIP(yy + ((int16_t)(1.402f * CVACC) * cr / CVACC));
                pRGB24->mG = /* G */ BYTECLIP(yy - ((int16_t)(0.344f * CVACC) * cb + (int16_t)(0.714f * CVACC) * cr) / CVACC);
                pRGB24->mB = /* B */ BYTECLIP(yy + ((int16_t)(1.772f * CVACC) * cb / CVACC));
#endif //JD_FORMAT_SWAP_RB	
				pRGB24++;
			}
		}
	}

	/* Squeeze up pixel table if a part of MCU is to be truncated */
	mx >>= jd->scale;
	if (rx < mx) {
		uint8_t *s, *d;
		uint16_t x, y;

		s = d = (uint8_t*)jd->workbuf;
		for (y = 0; y < ry; y++) {
			for (x = 0; x < rx; x++) {	/* Copy effective pixels */
				*d++ = *s++;
				*d++ = *s++;
				*d++ = *s++;
			}
			s += (mx - rx) * 3;	/* Skip truncated pixels */
		}
	}

	/* Convert RGB888 to RGB565 if needed */
	if (JD_FORMAT == 1) {
		uint8_t *s = (uint8_t*)jd->workbuf;
		uint16_t w, *d = (uint16_t*)s;
		uint16_t n = rx * ry;

		do {
#if(JD_FORMAT_SWAP_RB)	//使能RB交换,变为RGB格式
			w = (*s++) >> 3;				/* -----------BBBBB */
            w |= (*s++ & 0xFC) << 3;	/* -----GGGGGG----- */
			w |= (*s++ & 0xF8) << 8;		/* RRRRR----------- */
#else //默认的BGR格式
            w = (*s++ & 0xF8) << 8;		/* RRRRR----------- */
            w |= (*s++ & 0xFC) << 3;	/* -----GGGGGG----- */
            w |= *s++ >> 3;				/* -----------BBBBB */
#endif //JD_FORMAT_SWAP_RB	
			*d++ = w;
		} while (--n);
	}

	/* Output the RGB rectangular */
	return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; 
}

这样通过宏定义就可以选择输出RGB888还是BGR888,至于RGB565则不会受到此影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cp1300

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值