请教下,表盘指针图片旋转 ??

2019-12-14 12:14发布

本帖最后由 hpdell 于 2018-5-29 11:08 编辑

请教下,使用 GUI_MEMDEV_Rotate 旋转显示表盘指针图片 ?
使用函数 GUI_MEMDEV_Rotate ,图片旋转始终都是以图片的中心为基准的,有没有什么方法可以改一下啊 ?

另外,指针图片是不是需要做成 镜像的图片 ,吧镜像部分搞成透明 ??????

效果如下:
旋转图片-2.jpg (40.87 KB, 下载次数: 0) 下载附件 2018-5-29 09:32 上传


显示代码如下:

void GUI_MEMDEV_ColckRotaeShow(void)
{
        int      t0;   // 用于三个指针的计数
        int      t1;
        int      t2;

        GUI_MEMDEV_Select(hMemDest);
        GUI_MEMDEV_Write  (hMemLcd);  //将给定存储设备的内容写入当前选定的存储设备中,

        GUI_MEMDEV_Rotate(hMemSourceBk,
                                                hMemDest,
                                                0,  //      显示地址由 hMemDest、hMemLcd 决定
                                                0,  //      显示地址由 hMemDest、hMemLcd 决定
                                                0,  //      因为显示表盘不需要旋转,所以此次的值为0
                                                1000);

        // 第一个指针计数,用于旋转秒针
        t0 = 360 - (RotateSecond * 6);

        // 第二个指针计数,用于旋转分针
        t1 = 360 - (RotateMinute *6) -(RotateSecond /10);  //秒针每移动10秒,分钟移动的角度为1度
                                                               
       
  /*
           把小时 sTime.Hours%12是吧24小时制式sTime.Hours转化为12小时制,*30(因为小时时针每小时运行30度),
                 ((sTime.Minutes /10)*6) 这句是分钟每移动10分钟,小时时针移动 6度
        */
        t2 = 360 - (((RotateHour)%12) * 30) - ((RotateMinute /10)*6);


        GUI_MEMDEV_RotateHQ(hMemHour,
                                                hMemDest,
                                                100+56, // (RectDest.x1 - RectSource.x1) / 2,
                                                83,  //(RectDest.y1 - RectSource.y1) / 2,
                                                t2 * 1000,
                                                1000);



        GUI_MEMDEV_RotateHQ(hMemMinute,
                                                hMemDest,
                                                100+56, // (RectDest.x1 - RectSource.x1) / 2,
                                                43,  //(RectDest.y1 - RectSource.y1) / 2,
                                                t1 * 1000,
                                                1000);


        GUI_MEMDEV_RotateHQ(hMemSecond,
                                                hMemDest,
                                                100+59, // (RectDest.x1 - RectSource.x1) / 2,
                                                174/4+32,  //(RectDest.y1 - RectSource.y1) / 2,
                                                t0 * 1000,
                                                1000);



        GUI_MEMDEV_Select(0);                                                                                 
        GUI_MULTIBUF_Begin();                                                                                 
        GUI_MEMDEV_CopyToLCD            (hMemDest);                                                                                 
        GUI_MULTIBUF_End();

        RotateSecond ++;

        if(RotateSecond >= 60)
        {
                RotateSecond = 0;
                RotateMinute++;
                if(RotateMinute >= 60)
                {
                        RotateMinute =0;
                        RotateHour++;
                        if(RotateHour >= 24)
                        {
                                RotateHour=0;
                        }
                }
        }
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
16条回答
hpdell
2019-12-15 23:18
tongtong2009999 发表于 2018-12-18 11:28
怎么解决的,可以分享一下代码吗,谢谢


你好,最终修改了图片,

代码如下:

// 使用 流位图显示
//app图标描述结构体
typedef struct{
        const char         *pFileNamePath;   // 图标文件名路径
       
} CLOCK_BITMAP_ITEM_STREAM;

/*
流数据取数据说明如下:
1. 先准备好需要的图标图片,*.bmp,*.png格式的,必须带透明通道的图片
2. 使用 st 提供的工具软件 BmpCvtST.exe (版本v532或v5.40都行) 打开已准备好的图片
3. 打开后什么也不修改直接 点击 Files->Save as ... 选择 *.dta 格式 按保存
4. a: 如果选择 True color with alpha  格式保存的,是按照 每个像素 4 字节取码的 +16Byte
   b: 如果选择 High color with Alpha(565) 格式保存的,是按照 rgb565格式保存,另外还多了一个字节的透明通道数据
      实际是按照 3字节保存数据 +16Byte
5. 比如一个图片像素为 96*96,那么按照 565格式取码后的大小为 96*3*96+16大小
*/
static const CLOCK_BITMAP_ITEM_STREAM ClockStreamBitmapItemTab1[]={
// 图片旋转 只支持 argb8888 格式,切记切记
        "0:ClockSrteam/dta_ARGB8888/omega_367x332_SourceFile_ARGB8888.dta",
        "0:ClockSrteam/dta_ARGB8888/HourCen_ARGB8888.dta",        
        "0:ClockSrteam/dta_ARGB8888/MinuteCen_ARGB8888.dta",   
        "0:ClockSrteam/dta_ARGB8888/SecondCen_ARGB8888.dta",        
};


typedef struct
{
        const int xSize;
        const int ySize;
}  _ClockPosStreamTypeDef;

const _ClockPosStreamTypeDef  _ClockPosStream[]={

        367, 332,
        23,  166,
        25,  244,
        17,  268
};

typedef struct
{
        GUI_MEMDEV_Handle hMem1_Clock[4];      // 时钟表盘、表针,数组0表示表盘背景,1表示时针,2表示分针,3表示秒针
        GUI_MEMDEV_Handle hMem1_ClockDest;    // 目标内存
        GUI_MEMDEV_Handle hMem1_ClockLcd;     // 显示内存
       
        GUI_BITMAP       Bitmap[4];  // 时钟表盘、表针,数组0表示表盘背景,1表示时针,2表示分针,3表示秒针
        GUI_LOGPALETTE   Palette[4];

        uint8_t  *_acComBuff ;
        uint8_t  *_acClockBuf[4] ;   // 时钟表盘、表针,数组0表示表盘背景,1表示时针,2表示分针,3表示秒针

} _ClockPramTypeDef;

_ClockPramTypeDef  * _ClockParm = NULL;

#define DEG2RAD_180      (float)((float)3.1415926f / 180)   // 0.0174532924
#define MAG          3

/*
*********************************************************************************************************
*        函 数 名: InitDialogRTC
*        功能说明: 对话框回调函数的初始化消息
*        形    参: pMsg   消息指针变量
*        返 回 值: 无
*********************************************************************************************************
*/
void InitDialogRTC(void)
{
        GUI_MEMDEV_RTC_ClockInit();
}


/*
函数名称:GUI_MEMDEV_RTC_ClockInit
函数功能:初始化内存设备,在GUI_Init 之后调用也可以在 WM_INIT_DIALOG 这个里面调用一次
          初始化只执行一次即可
参数:无
返回值:无

*/
static void GUI_MEMDEV_RTC_ClockInit(void)
{
        FIL  CLOCK_File;
        FRESULT result;
        UINT bw;       
        int  i=0;
       
  if (BSP_SD_IsDetected() != SD_PRESENT)
  {
    printf((const char *)"RTC SD 卡不存在,请插入 ... ... ? ");
    return ;
  }        
       
        //此内存申请后就不释放了,因为程序一直在运行
        _ClockParm = (_ClockPramTypeDef *)mymalloc(SRAMEX, sizeof(_ClockPramTypeDef) );   //SRAMDTCM
       
        for(i=0;i<4;i++)
        {
                        result = f_open(&CLOCK_File, ClockStreamBitmapItemTab1.pFileNamePath,  FA_READ );
                        if (result != FR_OK)
                        {
                                printf("open file fail %d ",result );
                                myfree(SRAMEX,(void *) _ClockParm);
                                return;
                        }
                        _ClockParm->_acClockBuf = GUI_MYmalloc(CLOCK_File.obj.objsize );
                        _ClockParm->_acComBuff   = _ClockParm->_acClockBuf;       
                        result = f_read(&CLOCK_File, _ClockParm->_acComBuff, CLOCK_File.obj.objsize, &bw);
                        if (result != FR_OK)
                        {
                                __IO int cc;
                                for(cc=0;cc<i;cc++)
                                {
                                        _ClockParm->_acComBuff   = _ClockParm->_acClockBuf[cc];
                                        GUI_MYfree((void *) _ClockParm->_acComBuff);                 //使用完后释放内存       
                                }
                                f_close(&CLOCK_File);
                                myfree(SRAMEX,(void *) _ClockParm);
                                return ;
                        }
                        f_close(&CLOCK_File);       
        }
       
        for(i=0;i<4;i++)
        {
                // 适用与 emwin  > v5.32 argb / abgr 库 版本
                // 显示表盘背景,  在单片机上绘制 32bit BMP 图片数据文件,必须使用GUI_MEMDEV_CreateFixed32 这个函数
                        // 图片旋转只支持 32bit 格式的图片,切记切记   2018.06.14   21:10
                _ClockParm->hMem1_Clock = GUI_MEMDEV_CreateFixed32(0,   //创建具有 32bpp 颜 {MOD}深度和 GUICC_8888 颜 {MOD}转换的内存设备
                                                                                                                                                                                                                          0,
                                                                                                                                                _ClockPosStream.xSize,
                                                                                                                                                _ClockPosStream.ySize );       

                GUI_MEMDEV_Select(_ClockParm->hMem1_Clock);
                _ClockParm->_acComBuff   = _ClockParm->_acClockBuf;
                GUI_SetBkColor(GUI_TRANSPARENT );   //清除背景 {MOD} 0xFFC0C0C0  GUI_TRANSPARENT
                GUI_Clear();       
                GUI_CreateBitmapFromStream(&_ClockParm->Bitmap, &_ClockParm->Palette, _ClockParm->_acComBuff);
                GUI_DrawBitmap(&_ClockParm->Bitmap, 0, 0);                       
        }
       
        _ClockParm->hMem1_ClockDest = GUI_MEMDEV_CreateFixed32(  1024-367,   //最终显示的 x 地址
                                                                                                                                                                                                                                        24,                                               //最终显示的 y 地址
                                                                                                                                                _ClockPosStream[0].xSize,           //与显示最大表盘尺寸宽度一致即可
                                                                                                                                                _ClockPosStream[0].ySize );  

        _ClockParm->hMem1_ClockLcd = GUI_MEMDEV_CreateFixed32(   1024-367,   //最终显示的 x 地址
                                                                                                                                                                                                                                        24,                                                //最终显示的 y 地址
                                                                                                                                                _ClockPosStream[0].xSize,           //与显示最大表盘尺寸宽度一致即可
                                                                                                                                                _ClockPosStream[0].ySize );

//-----------------------------------------------------------------------------------------               
        GUI_MEMDEV_Select(0);       
        GUI_MEMDEV_CopyFromLCD          (_ClockParm->hMem1_ClockLcd);  //将 LCD 内容复制到存储设备
       
        // 释放申请内存
        for(i=0;i<4;i++)
        {
                _ClockParm->_acComBuff   = _ClockParm->_acClockBuf;
                GUI_MYfree((void *) _ClockParm->_acComBuff);                 //使用完后释放内存       
        }
//        myfree(SRAMEX,(void *) _ClockParm);  //这个 _ClockParm 参数不能够释放,因为程序一直在运行
       
        /* 配置回之前选择的目标窗口 */
//        WM_SelectWindow(hWinOld);       
}


/*
*********************************************************************************************************
*        函 数 名: Clock_DrawDisp
*        功能说明: 更新时钟表盘
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void Clock_DrawDisp(WM_MESSAGE * pMsg)
{
        int      t0;   // 用于三个指针的计数
        int      t1;
        int      t2;
        char buf[30];
       
        WM_HWIN hWin = pMsg->hWin;
       
        // Get the RTC current Time
        HAL_RTC_GetTime(&RtcHandle, &sTime, RTC_FORMAT_BIN);           // 时间与日期需要同时获取,切记切记,
        // Get the RTC current Date                                                                                             
        HAL_RTC_GetDate(&RtcHandle, &sDate, RTC_FORMAT_BIN);       
       
        t0 = 360 - (sTime.Seconds * 6);    // 第一个指针计数,用于旋转秒针

        // 第二个指针计数,用于旋转分针
        t1 = 360 - (sTime.Minutes *6) -(sTime.Seconds /10);  //秒针每移动10秒,分钟移动的角度为1度

  /*
           把小时 sTime.Hours%12是吧24小时制式sTime.Hours转化为12小时制,*30(因为小时时针每小时运行30度),
                 ((sTime.Minutes /10)*5) 这句是分钟每移动10分钟,小时时针移动 5度
        */
        t2 = 360 - (((sTime.Hours)%12) * 30) - ((sTime.Minutes /10)*5);       
               

        GUI_MEMDEV_Select(_ClockParm->hMem1_ClockDest);
        GUI_MEMDEV_Write  (_ClockParm->hMem1_ClockLcd);  //将给定存储设备的内容写入当前选定的存储设备中,
                                                  //即hMem1_ClockLcd -> hMem1_ClockDest

        GUI_BMP_ShowBkPicture();         // 使用 emwin  v5.40 abgr 版本,需要在此处重新绘制一下背景 {MOD},否则表盘不会显示透明功能
                                         // 如果使用单 {MOD}背景 {MOD},则此处不需要,但需要吧 GUI_CreateBitmapFromStream 此函数
                                                                                                                                         // 之前屏蔽的函数打开即可,切记切记  2018.07.05  sws
       
        GUI_MEMDEV_Rotate(_ClockParm->hMem1_Clock[0],
                                                _ClockParm->hMem1_ClockDest,
                                                0,  //      显示地址由 hMemDest、hMemLcd 决定
                                                0,  //      显示地址由 hMemDest、hMemLcd 决定
                                                0,  //      因为显示表盘不需要旋转,所以此次的值为0
                                                1000);
                                               
        GUI_MEMDEV_Rotate(_ClockParm->hMem1_Clock[1],
                                                _ClockParm->hMem1_ClockDest,
                                                157, // 显示时针计算方法,表盘的中心x坐标-时针的中心x坐标,偏移量
                                                                                              //已经在创建时设定好的,也就是以创建时的坐标为基准
                                                83,  
                                                t2 * 1000,
                                                1000);

        GUI_MEMDEV_Rotate(_ClockParm->hMem1_Clock[2],
                                                _ClockParm->hMem1_ClockDest,
                                                156,  
                                                44,   
                                                t1 * 1000,
                                                1000);

        GUI_MEMDEV_Rotate(_ClockParm->hMem1_Clock[3],
                                                _ClockParm->hMem1_ClockDest,
                                                161,
                                                32 ,  
                                                t0 * 1000,
                                                1000);

        GUI_MEMDEV_Select(0);                                                                                 
        GUI_MULTIBUF_Begin();                                                                                 
        GUI_MEMDEV_CopyToLCD            (_ClockParm->hMem1_ClockDest);                //将内容显示到 LCD 屏幕上                                                                 
        GUI_MULTIBUF_End();

        /* 更新 表盘里面的 星期  */
        sprintf(buf,
              "%s",
                    RtcWeek[sDate.WeekDay]);       
        TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT2), buf);

        /* 更新 表盘里面的 日期  */
        sprintf(buf,
              "%s",
                    apDaysRiQi[sDate.Date-1]);       
        TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT3), buf);       
       
       
}

一周热门 更多>