在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则不会受到此影响。