stm32 h743的jpeg压缩硬件压缩的测试实例及问题
代码就不上了,主要是抄袭实例代码
encode_dma.c
jpeg_utils.c
jpeg_utils.h
jpeg_utils_conf.h四个文件
问题描述:不管压缩什么图,jpg图像发绿(灰度图像无所谓),经过测试发现宽度128或64,高度任意的图像压缩后jpg是正常的,猜测是jpg压缩核的限制,所以对代码进行了修改,将bmp按顺序以128*16小块数据从左到右,从上到下读出进行压缩,压缩后的jpg数据顺序是对的,具体原因参考jpeg压缩原理中的压缩数据流存储顺序。硬件初始化时必须设置相应寄存器中的图像大小为128宽,高度为w*h/128,压缩结束后在生成的jpg文件中将图像的宽度和高度再修改为对应的w h即可。
另外rgb转YCRCB时,相关代码不要+128,溢出后会导致CR=0或者cb=0,改为127即可.
测试768*576的yuv图像需要33ms,1024*768的yuv图像需要65ms,yuv图像的话下面的代码需要重写,如果用rgb的时间更长,主要消耗在rgb转ycrcb上了
ycomp = (int32_t)(*(RED_Y_LUT + red)) + (int32_t)(*(GREEN_Y_LUT + green)) + (int32_t)(*(BLUE_Y_LUT + blue));
cbcomp = (int32_t)(*(RED_CB_LUT + red)) + (int32_t)(*(GREEN_CB_LUT + green)) + (int32_t)(*(BLUE_CB_RED_CR_LUT + blue)) + 127;
crcomp = (int32_t)(*(BLUE_CB_RED_CR_LUT + red)) + (int32_t)(*(GREEN_CR_LUT + green)) + (int32_t)(*(BLUE_CR_LUT + blue)) + 127;
此处压缩768*576的图像,如有其它分辨率的请相应修改。
重点jpeg_utils_conf.h中添加
#define JPEG_SWAP_RG 1 //这个没有什么用处,个人认为
#define JPEG_SWAP_RB 0 //BMP中红绿蓝存储为BGR顺序
encode_dma.c中添加:
#define JPEG_CHROMA_SAMPLING JPEG_420_SUBSAMPLING
#define JPEG_COLOR_SPACE JPEG_YCBCR_COLORSPACE #define JPEG_IMAGE_QUALITY 75
#define MAX_INPUT_WIDTH 128 //这里必须是128,否则图片会绿
#define MAX_INPUT_LINES 16
#define BLOCKCOLUMN 128
#define MAX_INPUT_BLOCKCOLUMN (768/BLOCKCOLUMN)
#define CHUNK_SIZE_IN ((uint32_t)(MAX_INPUT_WIDTH * BYTES_PER_PIXEL * MAX_INPUT_LINES))
#define CHUNK_SIZE_OUT ((uint32_t) (CHUNK_SIZE_IN/2))
BMP_GetInfo(pBmpFile, &Conf);
Conf.ImageHeight = 768*576/128;//重点,添加
Conf.ImageWidth = 128;//重点
JPEG_GetEncodeColorConvertFunc(&Conf, &pRGBToYCbCr_Convert_Function, &MCU_TotalNb);
Jpeg_OUT_BufferTab.DataBufferSize = 0;
Jpeg_OUT_BufferTab.State = JPEG_BUFFER_EMPTY;
ReadBmpRgbLines1(pBmpFile, Conf, Input_Data_Buffer ,&dataBufferSize);
//下面函数相当于从768*576的图像中,按顺序每次读取128*16大小的小块图像数据
static void ReadBmpRgbLines1(FIL *file, JPEG_ConfTypeDef Conf2, uint8_t * pDataBuffer, uint32_t *BufferSize)
{
uint32_t bytesReadfile = 1;
uint32_t CurrentBlockLine = 1;
*BufferSize = 0;
JPEG_ConfTypeDef Conf1;
Conf1.ImageHeight = 576;
Conf1.ImageWidth = 768;
while((CurrentLine <= Conf1.ImageHeight) && (CurrentBlockLine <= MAX_INPUT_LINES))
{
f_lseek (file,BMP_HEADER_SIZE + Conf1.ImageWidth *(Conf1.ImageHeight - CurrentLine)*3 + CurrentBlockColumn*BLOCKCOLUMN*3);
f_read (file, pDataBuffer , BLOCKCOLUMN*3 , (UINT*)(&bytesReadfile));
pDataBuffer += bytesReadfile;
*BufferSize += bytesReadfile;
CurrentLine +=1 ;
CurrentBlockLine += 1;
}
CurrentBlockColumn += 1;
if(CurrentBlockColumn == MAX_INPUT_BLOCKCOLUMN)
{
CurrentLineForRead += MAX_INPUT_LINES;
}
CurrentLine = CurrentLineForRead;
CurrentBlockColumn = CurrentBlockColumn%MAX_INPUT_BLOCKCOLUMN;
}