在LCD螢幕上漸變顯示sRGB所有範圍顏色, 最大可漸變16,581,375種顏色

舟清颺發表於2024-05-12

V1.0 2024/05/12 釋出於部落格園

目錄
  • 功能及原理
  • 函式
    • Get_Screeninfo( )
    • Clear_Screen( )
    • Displays_GradientColorEffect( )
  • 測試
    • FileIOLibrary.c
    • FileIOLibrary.h
    • testing.c
  • 結果

功能及原理

突發奇想將sRGB全部漸變顯示出來, 於是花了好幾個小時不斷除錯, 終於能夠漸變實現.

①能夠自動獲取開發板的LCD驅動引數,

②能夠重新整理螢幕為指定顏色(清屏)

③能夠在LCD螢幕上自然地漸變顯示顏色, 最大可漸變16,581,375種顏色, 可幀率, 顯示時間, 顏色範圍

參考下面網站的色表:

線上色彩搭配工具,RGB配色器 - 線上工具 - 字客網 (fontke.com)

顯示原理如下:

image

當幀率為24時(可調整), 精度x和用時y(秒)的關係:

image

函式

Get_Screeninfo( )

/**
 * @name      Get_Screeninfo
 * @brief     獲取LCD螢幕硬體的寬度、高度、色深
 * @param     Manager 接收LCD螢幕資訊
 * @param     lcdinfo [0]寬度 [1]高度 [2]色深
 * @return
 *      @retval    true 獲取成功
 *      @retval    false 獲取失敗
 * @date      2024/05/11
 * @version   1.0
 * @note
 * 使用示範
 * LcdInfo_t lcdinfo;
 * lcdinfo.lcd_fd_Path = "/dev/fb0";
 * Get_Screeninfo(&lcdinfo);
 */
bool Get_Screeninfo(LcdInfo_t *Manager)
{

    // 開啟LCD 裝置驅動 獲取檔案描述符 以讀寫許可權 注意返回的是數值!
    int lcd_fd = open(Manager->lcd_fd_Path, O_RDWR);
    if (-1 == lcd_fd)
    {
        perror("開啟LCD驅動檔案失敗");
        return false;
    }

    // 利用檔案控制函式獲取獲取lcd引數資訊, 獲取可變引數 "cat /usr/include/linux/fb.h"
    // 定義一個結構體變數接收返回的資訊
    struct fb_var_screeninfo vinfo;

    // 獲取資訊, 將資訊寫入上述的結構體變數中
    ioctl(lcd_fd, FBIOGET_VSCREENINFO, &vinfo);

    // 寫入LCD的寬度,高度,色深
    Manager->LcdWidth = vinfo.xres;
    Manager->LcdHeight = vinfo.yres;
    Manager->LcdBpp = vinfo.bits_per_pixel;
    // 關閉lcd驅動檔案
    close(lcd_fd);
    return true;
}

Clear_Screen( )

/**
 * @name      Clear_Screen
 * @brief     清屏函式, 重新整理螢幕為指定顏色
 * @param     Manager 要重新整理的螢幕資訊結構體
 * @param     color 要重新整理的顏色 0x00FFFFFF ARGB
 * @return
 *      @retval    true 獲取成功
 *      @retval    false 獲取失敗
 * @date      2024/05/11
 * @version   1.0
 * @note
 * 使用示範 Clear_Screen(&lcdinfo, 0x00FF0000); 重新整理為紅色
 */
bool Clear_Screen(LcdInfo_t *Manager, int color)
{
    // 開啟LCD裝置驅動檔案 讀寫方式
    int lcd_fd = open(Manager->lcd_fd_Path, O_RDWR);
    if (-1 == lcd_fd)
    {
        printf("開啟lcd裝置驅動檔案失敗!\n");
        return false;
    }

    // 對LCD進行記憶體對映  mmap函式 接收返回值
    int *lcd_mp = (int *)mmap(
        NULL,                                                           // 對映後的記憶體地址由核心自動分配
        Manager->LcdWidth * Manager->LcdHeight * (Manager->LcdBpp / 8), // 螢幕對應的位元組數
        PROT_READ | PROT_WRITE,                                         // 可讀可寫
        MAP_SHARED,                                                     // 該對映的記憶體空間可共享
        lcd_fd,                                                         // 檔案描述符
        0);                                                             // 偏移量0
    // 錯誤處理
    if (MAP_FAILED == lcd_mp)
    {
        printf("lcd裝置驅動檔案記憶體對映失敗!\n");
        return false;
    }

    // 把顏色分量寫入到申請的對映記憶體空間中,透過地址偏移實現訪問
    for (int i = 0; i < Manager->LcdWidth * Manager->LcdHeight; ++i)
    {
        lcd_mp[i] = color;
    }

    // 關閉LCD並解除記憶體對映
    munmap(lcd_mp, Manager->LcdWidth * Manager->LcdHeight * (Manager->LcdBpp / 8));
    // 關閉LCD裝置驅動檔案
    close(lcd_fd);

    return true;
}

Displays_GradientColorEffect( )

/**
 * @name      Displays_GradientColorEffect
 * @brief     在LCD螢幕上漸變顯示顏色, 最大可漸變16,581,375種顏色
 * @param     lcdinfo LCD螢幕資訊;
 * @param     FrameRatedx 顯示幀率24-60;
 * @param     SetShowTime 你要顯示的時間長度(秒)
 * @param     step 顏色精度(1-255) 越低表示顯示種數越多 最大可顯示255^3種 (51表示216種 24表示1331種)
 * @return
 *      @retval    true 提前達到預定顯示時間
 * @date      2024/05/12
 * @version   1.0
 * @note
 *      使用示範
 *       Displays_GradientColorEffect(&lcdinfo, FRAMERATED, 120, 24);
 *      顯示一輪所用時間為y=((255/step +1)^3)/FrameRatedx 秒
 *      請注意一輪的顯示時間長短
 */
bool Displays_GradientColorEffect(LcdInfo_t *lcdinfo, int FrameRatedx, int SetShowTime, int step)
{
    int SleepTime = 1000000 / FrameRatedx;                         // 將幀率轉換為微秒時間 幀間隔需要多少時間
    int SetFrameRatedxCount = (SetShowTime * 1000000) / SleepTime; // 使用者要求一共重新整理多少幀
    // 顯示精度 步進值 預設 51(step) 最大255 顯示顏色數量為 ((255/step)+1)^3

    // 開始的顏色分量
    unsigned int startColor = 0;
    // 當前顏色分量
    unsigned int CurrentColor = 0;
    // 計算最大顯示顏色數量
    unsigned long ShowCount = ((255 / step) + 1) * ((255 / step) + 1) * ((255 / step) + 1);
    // 計算一輪顯示需要的顯示時間 秒
    int ShowTime = ShowCount / FrameRatedx;

    // 解算得到顏色分量組成 ARGB
    // 控制紅色見漸變
    int r = (startColor >> 16) & 0xFF;
    bool flagR = true; // true 表示顏色由深到淺色 false表示顏色由淺色到深色

    // 控制綠色見漸變
    int g = (startColor >> 8) & 0xFF;
    bool flagG = true; // true 表示顏色由深到淺色 false表示顏色由淺色到深色

    // 控制藍色見漸變
    int b = startColor & 0xFF;
    bool flagB = true; // true 表示顏色由深到淺色 false表示顏色由淺色到深色
    printf("可以顯示: %d 塊色塊,\n", (255 / step) + 1);
    printf("可以顯示: %d 條色帶\n", (((255 / step) + 1) * ((255 / step) + 1)));
    printf("可以顯示: %lu 種顏色,\n", ShowCount);

    printf("每個色塊內有 %d 條色帶,\n", (255 / step) + 1);
    printf("每條色帶內由 %d 種顏色組成,\n", (255 / step) + 1);
    printf("每個色塊有 %d 種顏色,\n", ((255 / step) + 1)) * ((255 / step) + 1);

    printf("一次迴圈需要 %d秒 即 %d 分鐘才能顯示完成 \n", ShowTime, ShowTime / 60);

    while (1)
    {

        if (flagG)
        {
            for (g = 0x00; g <= 0xFF; g += step)
            {
                //               printf("\n");
                //               printf("新色塊開始(%#x)\n", CurrentColor);

                if (flagB)
                {
                    for (b = 0x00; b <= 0xFF; b += step)
                    {
                        //                       printf("新色帶:(%#x)\n", CurrentColor);
                        if (flagR)
                        {
                            // 00????
                            for (r = 0x00; r <= 0xFF; r += step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0xFF;
                            // FF????
                            flagR = !flagR;
                        }
                        else
                        {
                            // FF????
                            for (r = 0xFF; r >= 0x00; r -= step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0x00;
                            // 00????
                            flagR = !flagR;
                        }
                    }
                    b = 0xFF;
                    // ????FF
                    flagB = !flagB;
                }
                else
                {
                    // ????FF
                    for (b = 0xFF; b >= 0x00; b -= step) // 同色段漸變
                    {
                        //                        printf("新色帶:(%#x)\n", CurrentColor);
                        if (flagR)
                        {
                            // 00????
                            for (r = 0x00; r <= 0xFF; r += step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0xFF;
                            // FF????
                            flagR = !flagR;
                        }
                        else
                        {
                            // FF????
                            for (r = 0xFF; r >= 0x00; r -= step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0x00;
                            // 00????
                            flagR = !flagR;
                        }
                    }
                    b = 0x00;
                    // ????00
                    flagB = !flagB;
                }
            }
            g = 0xFF;
            // ??FF??
            flagG = !flagG;
        }
        else
        {
            // ??FF??
            for (g = 0xFF; g >= 0x00; g -= step) // 同色段漸變
            {
                //               printf("\n");
                //             printf("新色塊開始(%#x)\n", CurrentColor);
                if (flagB)
                {
                    for (b = 0x00; b <= 0xFF; b += step)
                    {
                        //          printf("新色帶:(%#x)\n", CurrentColor);
                        if (flagR)
                        {
                            // 00????
                            for (r = 0x00; r <= 0xFF; r += step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0xFF;
                            // FF????
                            flagR = !flagR;
                        }
                        else
                        {
                            // FF????
                            for (r = 0xFF; r >= 0x00; r -= step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0x00;
                            // 00????
                            flagR = !flagR;
                        }
                    }
                    b = 0xFF;
                    // ????FF
                    flagB = !flagB;
                }
                else
                {
                    // ????FF
                    for (b = 0xFF; b >= 0x00; b -= step) // 同色段漸變
                    {
                        //                  printf("新色帶:(%#x)\n", CurrentColor);
                        if (flagR)
                        {
                            // 00????
                            for (r = 0x00; r <= 0xFF; r += step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0xFF;
                            // FF????
                            flagR = !flagR;
                        }
                        else
                        {
                            // FF????
                            for (r = 0xFF; r >= 0x00; r -= step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0x00;
                            // 00????
                            flagR = !flagR;
                        }
                    }
                    b = 0x00;
                    // ????00
                    flagB = !flagB;
                }
            }
            g = 0x00;
            // ??00??
            flagG = !flagG;
        }
    }
}

測試

FileIOLibrary.c

/**
 * @file name : FileIOLibrary.c
 * @brief     : 實現檔案IO相關介面函式的封裝
 * @author    : RISE_AND_GRIND@163.com
 * @date      : 2024/05/11
 * @version   : 1.0
 * @note      : 模組化實現
 * CopyRight (c)  2023-2024   RISE_AND_GRIND@163.com   All Right Reseverd
 */
#include "FileIOLibrary.h"

/**
 * @name      Get_Screeninfo
 * @brief     獲取LCD螢幕硬體的寬度、高度、色深
 * @param     Manager 接收LCD螢幕資訊
 * @param     lcdinfo [0]寬度 [1]高度 [2]色深
 * @return
 *      @retval    true 獲取成功
 *      @retval    false 獲取失敗
 * @date      2024/05/11
 * @version   1.0
 * @note
 * 使用示範
 * LcdInfo_t lcdinfo;
 * lcdinfo.lcd_fd_Path = "/dev/fb0";
 * Get_Screeninfo(&lcdinfo);
 */
bool Get_Screeninfo(LcdInfo_t *Manager)
{

    // 開啟LCD 裝置驅動 獲取檔案描述符 以讀寫許可權 注意返回的是數值!
    int lcd_fd = open(Manager->lcd_fd_Path, O_RDWR);
    if (-1 == lcd_fd)
    {
        perror("開啟LCD驅動檔案失敗");
        return false;
    }

    // 利用檔案控制函式獲取獲取lcd引數資訊, 獲取可變引數 "cat /usr/include/linux/fb.h"
    // 定義一個結構體變數接收返回的資訊
    struct fb_var_screeninfo vinfo;

    // 獲取資訊, 將資訊寫入上述的結構體變數中
    ioctl(lcd_fd, FBIOGET_VSCREENINFO, &vinfo);

    // 寫入LCD的寬度,高度,色深
    Manager->LcdWidth = vinfo.xres;
    Manager->LcdHeight = vinfo.yres;
    Manager->LcdBpp = vinfo.bits_per_pixel;
    // 關閉lcd驅動檔案
    close(lcd_fd);
    return true;
}

/**
 * @name      Clear_Screen
 * @brief     清屏函式, 重新整理螢幕為指定顏色
 * @param     Manager 要重新整理的螢幕資訊結構體
 * @param     color 要重新整理的顏色 0x00FFFFFF ARGB
 * @return
 *      @retval    true 獲取成功
 *      @retval    false 獲取失敗
 * @date      2024/05/11
 * @version   1.0
 * @note
 * 使用示範 Clear_Screen(&lcdinfo, 0x00FF0000); 重新整理為紅色
 */
bool Clear_Screen(LcdInfo_t *Manager, int color)
{
    // 開啟LCD裝置驅動檔案 讀寫方式
    int lcd_fd = open(Manager->lcd_fd_Path, O_RDWR);
    if (-1 == lcd_fd)
    {
        printf("開啟lcd裝置驅動檔案失敗!\n");
        return false;
    }

    // 對LCD進行記憶體對映  mmap函式 接收返回值
    int *lcd_mp = (int *)mmap(
        NULL,                                                           // 對映後的記憶體地址由核心自動分配
        Manager->LcdWidth * Manager->LcdHeight * (Manager->LcdBpp / 8), // 螢幕對應的位元組數
        PROT_READ | PROT_WRITE,                                         // 可讀可寫
        MAP_SHARED,                                                     // 該對映的記憶體空間可共享
        lcd_fd,                                                         // 檔案描述符
        0);                                                             // 偏移量0
    // 錯誤處理
    if (MAP_FAILED == lcd_mp)
    {
        printf("lcd裝置驅動檔案記憶體對映失敗!\n");
        return false;
    }

    // 把顏色分量寫入到申請的對映記憶體空間中,透過地址偏移實現訪問
    for (int i = 0; i < Manager->LcdWidth * Manager->LcdHeight; ++i)
    {
        lcd_mp[i] = color;
    }

    // 關閉LCD並解除記憶體對映
    munmap(lcd_mp, Manager->LcdWidth * Manager->LcdHeight * (Manager->LcdBpp / 8));
    // 關閉LCD裝置驅動檔案
    close(lcd_fd);

    return true;
}

/**
 * @name      Displays_GradientColorEffect
 * @brief     在LCD螢幕上漸變顯示顏色, 最大可漸變16,581,375種顏色
 * @param     lcdinfo LCD螢幕資訊;
 * @param     FrameRatedx 顯示幀率24-60;
 * @param     SetShowTime 你要顯示的時間長度(秒)
 * @param     step 顏色精度(1-255) 越低表示顯示種數越多 最大可顯示255^3種 (51表示216種 24表示1331種)
 * @return
 *      @retval    true 提前達到預定顯示時間
 * @date      2024/05/12
 * @version   1.0
 * @note
 *      使用示範
 *       Displays_GradientColorEffect(&lcdinfo, FRAMERATED, 120, 24);
 *      顯示一輪所用時間為y=((255/step +1)^3)/FrameRatedx 秒
 *      請注意一輪的顯示時間長短
 */
bool Displays_GradientColorEffect(LcdInfo_t *lcdinfo, int FrameRatedx, int SetShowTime, int step)
{
    int SleepTime = 1000000 / FrameRatedx;                         // 將幀率轉換為微秒時間 幀間隔需要多少時間
    int SetFrameRatedxCount = (SetShowTime * 1000000) / SleepTime; // 使用者要求一共重新整理多少幀
    // 顯示精度 步進值 預設 51(step) 最大255 顯示顏色數量為 ((255/step)+1)^3

    // 開始的顏色分量
    unsigned int startColor = 0;
    // 當前顏色分量
    unsigned int CurrentColor = 0;
    // 計算最大顯示顏色數量
    unsigned long ShowCount = ((255 / step) + 1) * ((255 / step) + 1) * ((255 / step) + 1);
    // 計算一輪顯示需要的顯示時間 秒
    int ShowTime = ShowCount / FrameRatedx;

    // 解算得到顏色分量組成 ARGB
    // 控制紅色見漸變
    int r = (startColor >> 16) & 0xFF;
    bool flagR = true; // true 表示顏色由深到淺色 false表示顏色由淺色到深色

    // 控制綠色見漸變
    int g = (startColor >> 8) & 0xFF;
    bool flagG = true; // true 表示顏色由深到淺色 false表示顏色由淺色到深色

    // 控制藍色見漸變
    int b = startColor & 0xFF;
    bool flagB = true; // true 表示顏色由深到淺色 false表示顏色由淺色到深色
    printf("可以顯示: %d 塊色塊,\n", (255 / step) + 1);
    printf("可以顯示: %d 條色帶\n", (((255 / step) + 1) * ((255 / step) + 1)));
    printf("可以顯示: %lu 種顏色,\n", ShowCount);

    printf("每個色塊內有 %d 條色帶,\n", (255 / step) + 1);
    printf("每條色帶內由 %d 種顏色組成,\n", (255 / step) + 1);
    printf("每個色塊有 %d 種顏色,\n", ((255 / step) + 1)) * ((255 / step) + 1);

    printf("一次迴圈需要 %d秒 即 %d 分鐘才能顯示完成 \n", ShowTime, ShowTime / 60);

    while (1)
    {

        if (flagG)
        {
            for (g = 0x00; g <= 0xFF; g += step)
            {
                //               printf("\n");
                //               printf("新色塊開始(%#x)\n", CurrentColor);

                if (flagB)
                {
                    for (b = 0x00; b <= 0xFF; b += step)
                    {
                        //                       printf("新色帶:(%#x)\n", CurrentColor);
                        if (flagR)
                        {
                            // 00????
                            for (r = 0x00; r <= 0xFF; r += step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0xFF;
                            // FF????
                            flagR = !flagR;
                        }
                        else
                        {
                            // FF????
                            for (r = 0xFF; r >= 0x00; r -= step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0x00;
                            // 00????
                            flagR = !flagR;
                        }
                    }
                    b = 0xFF;
                    // ????FF
                    flagB = !flagB;
                }
                else
                {
                    // ????FF
                    for (b = 0xFF; b >= 0x00; b -= step) // 同色段漸變
                    {
                        //                        printf("新色帶:(%#x)\n", CurrentColor);
                        if (flagR)
                        {
                            // 00????
                            for (r = 0x00; r <= 0xFF; r += step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0xFF;
                            // FF????
                            flagR = !flagR;
                        }
                        else
                        {
                            // FF????
                            for (r = 0xFF; r >= 0x00; r -= step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0x00;
                            // 00????
                            flagR = !flagR;
                        }
                    }
                    b = 0x00;
                    // ????00
                    flagB = !flagB;
                }
            }
            g = 0xFF;
            // ??FF??
            flagG = !flagG;
        }
        else
        {
            // ??FF??
            for (g = 0xFF; g >= 0x00; g -= step) // 同色段漸變
            {
                //               printf("\n");
                //             printf("新色塊開始(%#x)\n", CurrentColor);
                if (flagB)
                {
                    for (b = 0x00; b <= 0xFF; b += step)
                    {
                        //          printf("新色帶:(%#x)\n", CurrentColor);
                        if (flagR)
                        {
                            // 00????
                            for (r = 0x00; r <= 0xFF; r += step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0xFF;
                            // FF????
                            flagR = !flagR;
                        }
                        else
                        {
                            // FF????
                            for (r = 0xFF; r >= 0x00; r -= step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0x00;
                            // 00????
                            flagR = !flagR;
                        }
                    }
                    b = 0xFF;
                    // ????FF
                    flagB = !flagB;
                }
                else
                {
                    // ????FF
                    for (b = 0xFF; b >= 0x00; b -= step) // 同色段漸變
                    {
                        //                  printf("新色帶:(%#x)\n", CurrentColor);
                        if (flagR)
                        {
                            // 00????
                            for (r = 0x00; r <= 0xFF; r += step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0xFF;
                            // FF????
                            flagR = !flagR;
                        }
                        else
                        {
                            // FF????
                            for (r = 0xFF; r >= 0x00; r -= step) // 同色段漸變
                            {
                                //               A              r           g        b
                                CurrentColor = (0x00 << 24) | (r << 16) | (g << 8) | b; // 生成顏色
                                Clear_Screen(lcdinfo, CurrentColor);
                                usleep(SleepTime);
                                // 達到要求時間, 退出程式
                                SetFrameRatedxCount--;
                                if (SetFrameRatedxCount == 0)
                                {
                                    return true;
                                }
                            }
                            r = 0x00;
                            // 00????
                            flagR = !flagR;
                        }
                    }
                    b = 0x00;
                    // ????00
                    flagB = !flagB;
                }
            }
            g = 0x00;
            // ??00??
            flagG = !flagG;
        }
    }
}

FileIOLibrary.h

#ifndef __FILEIOLIBRARY_H
#define __FILEIOLIBRARY_H

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <unistd.h>

// LCD裝置的相關資訊儲存
typedef struct
{
    char *lcd_fd_Path;      // LCD裝置驅動檔案地址 "/dev/fb0"
    unsigned int LcdWidth;  // LCD的寬度
    unsigned int LcdHeight; // LCD的高度
    unsigned int LcdBpp;    // LCD的色深
} LcdInfo_t;
/**
 * @name      Get_Screeninfo
 * @brief     獲取LCD螢幕硬體的寬度、高度、色深
 * @param     Manager 接收LCD螢幕驅動檔案
 * @param     lcdinfo [0]寬度 [1]高度 [2]色深
 * @return
 *      @retval    true 獲取成功
 *      @retval    false 獲取失敗
 * @date      2024/05/11
 * @version   1.0
 * @note
 * 使用示範
 * LcdInfo_t lcdinfo;
 * lcdinfo.lcd_fd_Path = "/dev/fb0";
 * Get_Screeninfo(&lcdinfo);
 */
bool Get_Screeninfo(LcdInfo_t *Manager);

/**
 * @name      Clear_Screen
 * @brief     清屏函式, 重新整理螢幕為指定顏色
 * @param     Manager 要重新整理的螢幕資訊結構體
 * @param     color 要重新整理的顏色 0x00FFFFFF ARGB
 * @return
 *      @retval    true 獲取成功
 *      @retval    false 獲取失敗
 * @date      2024/05/11
 * @version   1.0
 * @note
 * 使用示範 Clear_Screen(&lcdinfo, 0x00FF0000); 重新整理為紅色
 */
bool Clear_Screen(LcdInfo_t *Manager, int color);

/**
 * @name      Displays_GradientColorEffect
 * @brief     在LCD螢幕上漸變顯示顏色, 最大可漸變16,581,375種顏色
 * @param     lcdinfo LCD螢幕資訊;
 * @param     FrameRatedx 顯示幀率24-60;
 * @param     SetShowTime 你要顯示的時間長度(秒)
 * @param     step 顏色精度(1-255) 越低表示顯示種數越多 最大可顯示255^3種 (51表示216種 24表示1331種)
 * @return
 *      @retval    true 提前達到預定顯示時間
 * @date      2024/05/12
 * @version   1.0
 * @note
 *      使用示範
 *       Displays_GradientColorEffect(&lcdinfo, FRAMERATED, 120, 24);
 *      顯示一輪所用時間為y=((255/step +1)^3)/FrameRatedx 秒
 *      請注意一輪的顯示時間長短
 */
bool Displays_GradientColorEffect(LcdInfo_t *lcdinfo, int FrameRatedx, int SetShowTime, int step);

#endif

testing.c

#include "FileIOLibrary.h"

#define FRAMERATED 24 // 幀率
int main(int argc, char const *argv[])
{
    LcdInfo_t lcdinfo;
    lcdinfo.lcd_fd_Path = "/dev/fb0";
    Get_Screeninfo(&lcdinfo);
    printf("高度 %d\n", lcdinfo.LcdHeight);
    printf("寬度 %d\n", lcdinfo.LcdWidth);
    printf("色深 %d\n", lcdinfo.LcdBpp);
    Displays_GradientColorEffect(&lcdinfo, FRAMERATED, 120, 51);
}

結果

[root@GEC6818 /yuyiworkspace]#./cheak
高度 480
寬度 800
色深 32
可以顯示: 6 塊色塊,
可以顯示: 36 條色帶
可以顯示: 216 種顏色,
每個色塊內有 6 條色帶,
每條色帶內由 6 種顏色組成,
每個色塊有 6 種顏色,
一次迴圈需要 9秒 即 0 分鐘才能顯示完成

[root@GEC6818 /yuyiworkspace]#./0157
高度 480
寬度 800
色深 32
可以顯示: 11 塊色塊,
可以顯示: 121 條色帶
可以顯示: 1331 種顏色,
每個色塊內有 11 條色帶,
每條色帶內由 11 種顏色組成,
每個色塊有 11 種顏色,
一次迴圈需要 55秒 即 0 分鐘才能顯示完成

[root@GEC6818 /yuyiworkspace]#./0157
高度 480
寬度 800
色深 32
可以顯示: 6 塊色塊,
可以顯示: 36 條色帶
可以顯示: 216 種顏色,
每個色塊內有 6 條色帶,
每條色帶內由 6 種顏色組成,
每個色塊有 6 種顏色,
一次迴圈需要 9秒 即 0 分鐘才能顯示完成

新色塊開始(0)
新色帶:(0)
新色帶:(0xff0000)
新色帶:(0x33)
新色帶:(0xff0066)
新色帶:(0x99)
新色帶:(0xff00cc)

新色塊開始(0xff)
新色帶:(0xff)
新色帶:(0xff33ff)
新色帶:(0x33cc)
新色帶:(0xff3399)
新色帶:(0x3366)
新色帶:(0xff3333)

新色塊開始(0x3300)
新色帶:(0x3300)
新色帶:(0xff6600)
新色帶:(0x6633)
新色帶:(0xff6666)
新色帶:(0x6699)
新色帶:(0xff66cc)

新色塊開始(0x66ff)
新色帶:(0x66ff)
新色帶:(0xff99ff)
新色帶:(0x99cc)
新色帶:(0xff9999)
新色帶:(0x9966)
新色帶:(0xff9933)

新色塊開始(0x9900)
新色帶:(0x9900)
新色帶:(0xffcc00)
新色帶:(0xcc33)
新色帶:(0xffcc66)
新色帶:(0xcc99)
新色帶:(0xffcccc)

新色塊開始(0xccff)
新色帶:(0xccff)
新色帶:(0xffffff)
新色帶:(0xffcc)
新色帶:(0xffff99)
新色帶:(0xff66)
新色帶:(0xffff33)

新色塊開始(0xff00)
新色帶:(0xff00)
新色帶:(0xffff00)
新色帶:(0xff33)
新色帶:(0xffff66)
新色帶:(0xff99)
新色帶:(0xffffcc)

新色塊開始(0xffff)
新色帶:(0xffff)
新色帶:(0xffccff)
新色帶:(0xcccc)
新色帶:(0xffcc99)
新色帶:(0xcc66)
新色帶:(0xffcc33)

新色塊開始(0xcc00)
新色帶:(0xcc00)
新色帶:(0xff9900)
新色帶:(0x9933)
新色帶:(0xff9966)
新色帶:(0x9999)
新色帶:(0xff99cc)

新色塊開始(0x99ff)
新色帶:(0x99ff)
新色帶:(0xff66ff)
新色帶:(0x66cc)
新色帶:(0xff6699)
新色帶:(0x6666)
新色帶:(0xff6633)

新色塊開始(0x6600)
新色帶:(0x6600)
新色帶:(0xff3300)
新色帶:(0x3333)
新色帶:(0xff3366)
新色帶:(0x3399)
新色帶:(0xff33cc)

新色塊開始(0x33ff)
新色帶:(0x33ff)
新色帶:(0xff00ff)
新色帶:(0xcc)
新色帶:(0xff0099)
新色帶:(0x66)
新色帶:(0xff0033)

新色塊開始(0)
新色帶:(0)
新色帶:(0xff0000)
新色帶:(0x33)
新色帶:(0xff0066)
新色帶:(0x99)
新色帶:(0xff00cc)

新色塊開始(0xff)
新色帶:(0xff)
新色帶:(0xff33ff)
新色帶:(0x33cc)
新色帶:(0xff3399)
新色帶:(0x3366)
新色帶:(0xff3333)

新色塊開始(0x3300)
新色帶:(0x3300)
新色帶:(0xff6600)
新色帶:(0x6633)
新色帶:(0xff6666)
新色帶:(0x6699)
新色帶:(0xff66cc)

新色塊開始(0x66ff)
新色帶:(0x66ff)
新色帶:(0xff99ff)
新色帶:(0x99cc)
新色帶:(0xff9999)
新色帶:(0x9966)
新色帶:(0xff9933)

新色塊開始(0x9900)
新色帶:(0x9900)
新色帶:(0xffcc00)
新色帶:(0xcc33)
新色帶:(0xffcc66)
新色帶:(0xcc99)
新色帶:(0xffcccc)

新色塊開始(0xccff)
新色帶:(0xccff)
新色帶:(0xffffff)
新色帶:(0xffcc)
新色帶:(0xffff99)
新色帶:(0xff66)
新色帶:(0xffff33)

新色塊開始(0xff00)
新色帶:(0xff00)
新色帶:(0xffff00)
新色帶:(0xff33)
新色帶:(0xffff66)
新色帶:(0xff99)
新色帶:(0xffffcc)

新色塊開始(0xffff)
新色帶:(0xffff)
新色帶:(0xffccff)
新色帶:(0xcccc)
新色帶:(0xffcc99)
新色帶:(0xcc66)
新色帶:(0xffcc33)

新色塊開始(0xcc00)
新色帶:(0xcc00)
新色帶:(0xff9900)
新色帶:(0x9933)
新色帶:(0xff9966)
新色帶:(0x9999)
新色帶:(0xff99cc)

新色塊開始(0x99ff)
新色帶:(0x99ff)
新色帶:(0xff66ff)
新色帶:(0x66cc)
新色帶:(0xff6699)
新色帶:(0x6666)
新色帶:(0xff6633)

新色塊開始(0x6600)
新色帶:(0x6600)
新色帶:(0xff3300)
新色帶:(0x3333)
新色帶:(0xff3366)
新色帶:(0x3399)
新色帶:(0xff33cc)

新色塊開始(0x33ff)
新色帶:(0x33ff)
新色帶:(0xff00ff)
新色帶:(0xcc)
新色帶:(0xff0099)
新色帶:(0x66)
新色帶:(0xff0033)

相關文章