请教下,使用 stm32f7x的硬件 jpeg 解码功能,图片不能够横屏显示

2019-07-20 14:06发布

本帖最后由 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)                           // 使用这个后,图片下半部分可以显示字符
              {
              }  
            }
    }
  }   
}



显示效果图片如下:

正常的竖屏显示,

竖屏.png


竖屏 180 度 显示图片如下:

竖屏180.png

这个竖屏 180度显示,字符汉字都已经正常显示了,唯独图片没有,需要修改哪里 ??

旋转180度显示图片的地址计算我是参考我的 图形显示参数修改的,显示图形任意方向显示是没有问题的

图片下半部分显示字符效果如下:
下半部分显示字符.png


图片下半部分 不 显示字符效果如下:

下半部分不显示字符.png








友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
5条回答
正点原子
1楼-- · 2019-07-20 15:56
 精彩回答 2  元偷偷看……
taizonglai
2楼-- · 2019-07-20 18:15
参考我们的F7的jpeg硬件解码,就有横竖屏显示的!
hpdell
3楼-- · 2019-07-20 21:51
本帖最后由 hpdell 于 2017-5-20 20:35 编辑
zuozhongkai 发表于 2017-5-20 14:56
参考我们的F7的jpeg硬件解码,就有横竖屏显示的!

你好,没有看到你们关于 这个硬件解码 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;
}


hpdell
4楼-- · 2019-07-21 01:18
 精彩回答 2  元偷偷看……
小恒心
5楼-- · 2019-07-21 06:46
 精彩回答 2  元偷偷看……

一周热门 更多>