本帖最后由 hpdell 于 2017-5-20 15:06 编辑
请教下,使用 stm32f7x的硬件 jpeg 解码功能,图片不能够横屏显示??
但是 显示字符,画图等完全可以横屏显示(四个方向可以任意显示),
还有在图片上显示字符,具体见下面程序的描述
jpeg 解码函数如下:
// _path 文件佳及路径
uint8_t JPEG_Display(char *_path)
{
uint32_t TimeBegin, TimeEnd;
uint32_t xPos = 0, yPos = 0;
FRESULT res;
FATFS * _jpeg_fs = 0;
TimeBegin = HAL_GetTick();
_jpeg_fs = (FATFS *)mymalloc(SRAMIN, sizeof(FATFS));
if( (!_jpeg_fs) )
return 0xff;
/*##-4- Register the file system object to the FatFs module ##############*/
res = f_mount(_jpeg_fs, (TCHAR const*)"0:", 0); // == FR_OK)
if(res == FR_OK )
{
/*##-5- Open the JPG file with read access #############################*/
res = f_open(&JPEG_File, (TCHAR const*)_path, FA_READ);
if(res == FR_OK )
{
/*##-6- JPEG decoding with IT (Not Blocking ) Method ################*/
JPEG_Decode_IT(&JPEG_Handle, &JPEG_File, JPEG_OUTPUT_DATA_BUFFER);
/*##-7- Wait till end of JPEG decoding and perfom Input/Output Processing in BackGround #*/
do
{
JPEG_InputHandler(&JPEG_Handle);
JpegProcessing_End = JPEG_OutputHandler(&JPEG_Handle);
}while(JpegProcessing_End == 0);
/*##-8- Get JPEG Info ###############################################*/
HAL_JPEG_GetInfo(&JPEG_Handle, &JPEG_Info);
printf("JPEG_Info.ImageWidth = %d
", JPEG_Info.ImageWidth);
printf("JPEG_Info.ImageHeight = %d
", JPEG_Info.ImageHeight);
/*##-9- Copy RGB decoded Data to the display FrameBuffer ############*/
if(( g_LcdDirection == 0) || (g_LcdDirection == 2)) // 竖屏,竖屏180
{
xPos = (BSP_LCD_GetXSize() - JPEG_Info.ImageWidth) / 2;
yPos = (BSP_LCD_GetYSize() - JPEG_Info.ImageHeight) / 2;
}
else // 横屏,横屏180
{
xPos = (BSP_LCD_GetYSize() - JPEG_Info.ImageWidth) / 2;
yPos = (BSP_LCD_GetXSize() - JPEG_Info.ImageHeight) / 2;
}
JPEG_DMA2D_CopyBuffer((uint32_t *)JPEG_OUTPUT_DATA_BUFFER, (uint32_t *)JPEG_LCD_FRAME_BUFFER,
xPos , yPos,
JPEG_Info.ImageWidth, JPEG_Info.ImageHeight);
/*##-10- Close the JPG file ##########################################*/
f_close(&JPEG_File);
}
else
{
printf("JPEG_Display f_open Error
");
}
}
else
{
printf("JPEG_Display f_mount Error
");
}
TimeEnd = HAL_GetTick();
printf("JPEG Display End ... ... %dms
" , TimeEnd - TimeBegin);
// 显示文件名
BSP_LTDC_DispStringAt(240, 1280/2-230, LCD_COLOR_BLUE, // 显示的文本颜 {MOD}
LCD_COLOR_TRANSPARENT, // 显示的背景颜 {MOD}
&FontAscii16x24,
(uint8_t *)_path); //
BSP_LTDC_DispStringAt(240, 1280/2-195, LCD_COLOR_BLUE, // 显示的文本颜 {MOD}
LCD_COLOR_TRANSPARENT, // 显示的背景颜 {MOD}
&FontAscii16x24,
(uint8_t *)"硬件解码JPEG显示 OK");
return 0;
}
/**
* @brief Copy the Decoded image to the display Frame buffer.
* @param pSrc: Pointer to source buffer
* @param pDst: Pointer to destination buffer
* @param x: destination horizenatl offset.
* @param y: destination Vertical offset.
* @param xSize: image width
* @param ysize: image Height
* @retval None
*/
static void JPEG_DMA2D_CopyBuffer(uint32_t *pSrc, uint32_t *pDst,
uint16_t x, uint16_t y,
uint16_t xsize, uint16_t ysize)
{
#if 1
#define DMA2D_Handle hdma2d_eval
#else
static DMA2D_HandleTypeDef DMA2D_Handle;
#endif
uint32_t source = (uint32_t)pSrc;
uint32_t destination = 0;
uint16_t OutputOffset = 0; // 行偏移
uint16_t NumberOfLine = 0; // 行数,表示我们显示的数据需要的行数
uint16_t PixelPerLine = 0; // 每行像素数, 每行需要显示多少个像素点
uint16_t _usX, _usY, _usWidth, _usHeight;
_usX = x;
_usY = y;
_usWidth = xsize;
_usHeight = ysize;
destination = (uint32_t)pDst;
/*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/
DMA2D_Handle.Init.Mode = DMA2D_M2M_PFC;
if (g_LcdDirection == 0) // 竖屏 LCD 屏 默认的扫描方向
{
destination += (LTDC_PIX_SIZE * (uint32_t)(_usY * LCD_PIXEL_WIDTH + _usX)); // 竖屏 ok
OutputOffset = LCD_PIXEL_WIDTH - _usWidth;
NumberOfLine = _usHeight;
PixelPerLine = _usWidth;
}
//注:在计算地址(XaddrPutPixel = xxx)里面使用到的 - _usHeight,- _usWidth,原因为
// lcd 屏的x,y 方向是可以自增的,所以需要 减去高度与宽度(意思就是反向显示)
else if (g_LcdDirection == 2) // 竖屏 180°
{
destination += (LTDC_PIX_SIZE * (uint32_t)((LCD_PIXEL_HEIGHT - _usHeight - _usY - 1) * LCD_PIXEL_WIDTH + (LCD_PIXEL_WIDTH - _usWidth - _usX - 1))); // 180°竖屏
OutputOffset = LCD_PIXEL_WIDTH - _usWidth;
NumberOfLine = _usHeight ;
PixelPerLine = _usWidth;
}
else if (g_LcdDirection == 1) // 横屏
{
destination += (LTDC_PIX_SIZE * (uint32_t)( (_usX * LCD_PIXEL_WIDTH ) + (LCD_PIXEL_WIDTH - _usHeight - _usY - 1))); // 横屏
OutputOffset = LCD_PIXEL_WIDTH - _usHeight;
NumberOfLine = _usWidth ;
PixelPerLine = _usHeight ;
}
else if (g_LcdDirection == 3) // 横屏180°
{
destination += (LTDC_PIX_SIZE * (uint32_t)((LCD_PIXEL_HEIGHT - _usX - _usWidth - 1) * LCD_PIXEL_WIDTH + _usY)); // 横屏180
OutputOffset = LCD_PIXEL_WIDTH - _usHeight;
NumberOfLine = _usWidth ;
PixelPerLine = _usHeight ;
}
DMA2D_Handle.Init.OutputOffset = OutputOffset;
DMA2D_Handle.Init.AlphaInverted = DMA2D_REGULAR_ALPHA; /* No Output Alpha Inversion*/
DMA2D_Handle.Init.RedBlueSwap = DMA2D_RB_REGULAR; /* No Output Red & Blue swap */
/*##-2- DMA2D Callbacks Configuration ######################################*/
DMA2D_Handle.XferCpltCallback = NULL;
/*##-3- Foreground Configuration ###########################################*/
DMA2D_Handle.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
DMA2D_Handle.LayerCfg[1].InputAlpha = 0xFF;
#if (JPEG_RGB_FORMAT == JPEG_ARGB8888)
DMA2D_Handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
DMA2D_Handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
#elif (JPEG_RGB_FORMAT == JPEG_RGB888)
DMA2D_Handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB888;
DMA2D_Handle.Init.ColorMode = DMA2D_OUTPUT_RGB888;
#elif (JPEG_RGB_FORMAT == JPEG_RGB565)
DMA2D_Handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
DMA2D_Handle.Init.ColorMode = DMA2D_OUTPUT_RGB565;
#endif /* JPEG_RGB_FORMAT * */
DMA2D_Handle.LayerCfg[1].InputOffset = 0;
DMA2D_Handle.LayerCfg[1].RedBlueSwap = DMA2D_RB_REGULAR; /* No ForeGround Red/Blue swap */
DMA2D_Handle.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA; /* No ForeGround Alpha inversion */
DMA2D_Handle.Instance = DMA2D;
/* DMA2D Initialization */
if(HAL_DMA2D_Init(&DMA2D_Handle) == HAL_OK)
{
if(HAL_DMA2D_ConfigLayer(&DMA2D_Handle, 1) == HAL_OK)
{
if (HAL_DMA2D_Start(&DMA2D_Handle, source, destination, PixelPerLine, NumberOfLine ) == HAL_OK)
{
// Polling For DMA transfer
// HAL_DMA2D_PollForTransfer(&DMA2D_Handle, 10000); // 使用这个后,图片下半部分 不 能够显示字符 ??
while (DMA2D->CR & DMA2D_CR_START) // 使用这个后,图片下半部分可以显示字符
{
}
}
}
}
}
显示效果图片如下:
正常的竖屏显示,
竖屏 180 度 显示图片如下:
这个竖屏 180度显示,字符汉字都已经正常显示了,唯独图片没有,需要修改哪里 ??
旋转180度显示图片的地址计算我是参考我的 图形显示参数修改的,显示图形任意方向显示是没有问题的
图片下半部分显示字符效果如下:
图片下半部分 不 显示字符效果如下:
你好,没有看到你们关于 这个硬件解码 jpg 图片显示的 横竖屏 函数啊 ??
函数如下,望指教:
//JPEG硬件解码图片
//注意:
//1,待解吗图片的分辨率,必须小于等于屏幕的分辨率!
//2,请保证图片的宽度是16的倍数,以免左侧出现花纹.
//pname:图片名字(带路径)
//返回值:0,成功
// 其他,失败
u8 hjpgd_decode(u8* pname)
{
FIL* ftemp;
u16* rgb565buf;
vu32 timecnt=0;
u8 fileover=0;
u8 i=0;
u8 res;
u32 mcublkindex=0;
res=JPEG_Core_Init(&hjpgd); //初始化JPEG内核
if(res)return 1;
ftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //申请内存
if(f_open(ftemp,(char*)pname,FA_READ)!=FR_OK) //打开图片失败
{
JPEG_Core_Destroy(&hjpgd);
myfree(SRAMIN,ftemp); //释放内存
return 2;
}
rgb565buf=mymalloc(SRAMEX,800*480*2); //申请整帧内存
JPEG_Decode_Init(&hjpgd); //初始化硬件JPEG解码器
for(i=0;i<JPEG_DMA_INBUF_NB;i++)
{
res=f_read(ftemp,hjpgd.inbuf.buf,JPEG_DMA_INBUF_LEN,&br);//填满所有输入数据缓冲区
if(res==FR_OK&&br)
{
hjpgd.inbuf.size=br; //读取
hjpgd.inbuf.sta=1; //标记buf满
}
if(br==0)break;
}
JPEG_IN_OUT_DMA_Init((u32)hjpgd.inbuf[0].buf,(u32)hjpgd.outbuf[0].buf,hjpgd.inbuf[0].size,JPEG_DMA_OUTBUF_LEN);//配置DMA
jpeg_in_callback=jpeg_dma_in_callback; //JPEG DMA读取数据回调函数
jpeg_out_callback=jpeg_dma_out_callback; //JPEG DMA输出数据回调函数
jpeg_eoc_callback=jpeg_endofcovert_callback; //JPEG 解码结束回调函数
jpeg_hdp_callback=jpeg_hdrover_callback; //JPEG Header解码完成回调函数
JPEG_DMA_Start(); //启动DMA传输
while(1)
{
SCB_CleanInvalidateDCache(); //清空D catch
if(hjpgd.inbuf[hjpgd.inbuf_write_ptr].sta==0&&fileover==0) //有buf为空
{
res=f_read(ftemp,hjpgd.inbuf[hjpgd.inbuf_write_ptr].buf,JPEG_DMA_INBUF_LEN,&br);//填满一个缓冲区
if(res==FR_OK&&br)
{
hjpgd.inbuf[hjpgd.inbuf_write_ptr].size=br; //读取
hjpgd.inbuf[hjpgd.inbuf_write_ptr].sta=1; //buf满
}else if(br==0)
{
timecnt=0; //清零计时器
fileover=1; //文件结束了...
}
if(hjpgd.indma_pause==1&&hjpgd.inbuf[hjpgd.inbuf_read_ptr].sta==1)//之前是暂停的了,继续传输
{
JPEG_IN_DMA_Resume((u32)hjpgd.inbuf[hjpgd.inbuf_read_ptr].buf,hjpgd.inbuf[hjpgd.inbuf_read_ptr].size); //继续下一次DMA传输
hjpgd.indma_pause=0;
}
hjpgd.inbuf_write_ptr++;
if(hjpgd.inbuf_write_ptr>=JPEG_DMA_INBUF_NB)hjpgd.inbuf_write_ptr=0;
}
if(hjpgd.outbuf[hjpgd.outbuf_read_ptr].sta==1) //buf里面有数据要处理
{
mcublkindex+=hjpgd.ycbcr2rgb(hjpgd.outbuf[hjpgd.outbuf_read_ptr].buf,(u8*)rgb565buf,mcublkindex,hjpgd.outbuf[hjpgd.outbuf_read_ptr].size);
hjpgd.outbuf[hjpgd.outbuf_read_ptr].sta=0; //标记buf为空
hjpgd.outbuf[hjpgd.outbuf_read_ptr].size=0; //数据量清空
hjpgd.outbuf_read_ptr++;
if(hjpgd.outbuf_read_ptr>=JPEG_DMA_OUTBUF_NB)hjpgd.outbuf_read_ptr=0;//限制范围
if(mcublkindex==hjpgd.total_blks)
{
break;
}
}else if(hjpgd.outdma_pause==1&&hjpgd.outbuf[hjpgd.outbuf_write_ptr].sta==0) //out暂停,且当前writebuf已经为空了,则恢复out输出
{
JPEG_OUT_DMA_Resume((u32)hjpgd.outbuf[hjpgd.outbuf_write_ptr].buf,JPEG_DMA_OUTBUF_LEN);//继续下一次DMA传输
hjpgd.outdma_pause=0;
}
timecnt++;
if(fileover)//文件结束后,及时退出,防止死循环
{
if(hjpgd.state==JPEG_STATE_NOHEADER)break; //解码失败了
if(timecnt>0X3FFF)break; //超时退出
}
}
if(hjpgd.state==JPEG_STATE_FINISHED) //解码完成了
{
piclib_fill_color(picinfo.S_XOFF,picinfo.S_YOFF,hjpgd.Conf.ImageWidth,hjpgd.Conf.ImageHeight,rgb565buf);
}
myfree(SRAMIN,ftemp);
myfree(SRAMEX,rgb565buf);
JPEG_Core_Destroy(&hjpgd);
return 0;
}
一周热门 更多>