qt实现颜色十六进制转换为rgb并且进行扩展

本文介绍了一个使用Qt编写的代码,将16进制颜色转换为RGB,并通过扩展算法生成256种颜色点,存储在.txt文件中。代码包括颜色转换、颜色扩展和文件创建功能,适用于创建色板。此外,还讨论了当颜色点超过需求时,如何使用均匀采样来减小色差。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、转换为rgb

二、扩展rgb颜色

三、生成.txt文件储存rgb颜色点

四、补充代码

五、运行结果

六、补充(均匀采样)


最近需要使用qt来创建一个色板用于图像显示,而色板是十六进制的,网上的在线转换只能一个一个进行转换,比较麻烦(ˉ▽ˉ;)...,所以小写一个代码进行格式转换。由于色板只有30多种颜色,这里会进行扩展至256种颜色(这里采用两种颜色取中值的办法进行扩展),最终生成一个.txt文件用来存储这256个rgb颜色点。话不多说,直接上代码!

一、转换为rgb

void Widget::changeColor()
{
    //数组清零
    memset(color_rgb_1, 0, sizeof(color_rgb_1));
    memset(color_rgb_2, 0, sizeof(color_rgb_2));
    int r, g, b;
    int color_count = 0;
    int loop_count = 0;
    int *p_rgb = color_rgb_1;
    //16进制颜色数据
    string color_hex[] = {  "#EDB603","#EF9906","#FA7B06","#FE5A04","#E14B18",
                            "#E32E19","#D21C33","#B71048","#900956","#820178",
                            "#61058F","#4D08B0","#361ABC","#1F29D9","#1A42D5",
                            "#0755FD","#076BDB","#018CF5","#0990F1","#10C0E5",
                            "#19BCBB","#33E4C8","#4BE7A6","#6CF990","#82F47B",
                            "#9FF95C","#BCEB4F","#CAE22C","#DACE18","#F2B50d",
                            "#F49F04"};

    //rgb转化
    for(int i = 0; i <= 30; i++)
    {
        if (color_hex[i].at(0) == '#') {
            color_hex[i] = color_hex[i].erase(0, 1);
        }
        //提取rgb值
        istringstream(color_hex[i].substr(0, 2)) >> hex >> r;
        istringstream(color_hex[i].substr(2, 2)) >> hex >> g;
        istringstream(color_hex[i].substr(4, 2)) >> hex >> b;
        //把提取的rgb存储在数组里
        color_rgb_1[color_count] = r;
        color_rgb_1[color_count + 1] = g;
        color_rgb_1[color_count + 2] = b;

        if(i != 30)
        {
            color_count += 3;
        }
        loop_count++;

    }
    createFile(extendColor(p_rgb, p_rgb, loop_count, recursion_count));
}

二、扩展rgb颜色

/*
    功能说明:扩展rgb颜色点
    参数说明:p_rgb - 移位指针1
             p2_rgb - 移位指针2
             color_rgb_num - rgb颜色点的数量
             recursion_count - 递归的次数
    返回值 :一个指向数组的整型指针
*/
int *Widget::extendColor(int *p_rgb, int *p2_rgb, int color_rgb_num, int recursion_count)
{
    int r, g, b;
    int loop_count = 0;     //循环次数
    int extend_num = color_rgb_num * 2 - 1;     //扩展后的颜色点数

    //递归次数达到3次,也就是扩展到了241个颜色点
    if(recursion_count == 3)
    {
        memset(color_rgb_1, 0, sizeof(color_rgb_1));
        //补充15个颜色点
        int lack_num = (256 - color_rgb_num) * 2;
        for(int i = 0; i < lack_num; i++)
        {
            //正常赋值
            if(i % 2 == 0)
            {
                for(int j = 0; j < 3; j++)
                {
                    color_rgb_1[i * 3 + j] = *p_rgb;
                    p_rgb++;
                }
            }
            //取两个颜色点(r,g,b)的中值再赋值
            else
            {
                r = (*p2_rgb + *(p2_rgb + 3)) / 2;
                g = (*(p2_rgb + 1) + *(p2_rgb + 3 + 1)) / 2;
                b = (*(p2_rgb + 2) + *(p2_rgb + 3 + 2)) / 2;
                color_rgb_1[i * 3] = r;
                color_rgb_1[i * 3 + 1] = g;
                color_rgb_1[i * 3 + 2] = b;
                p2_rgb += 3;
            }
        }
        
        //补充剩下的颜色点,凑到256个
        for(int k = lack_num; k < 256; k++)
        {
            for(int j = 0; j < 3; j++)
            {
                color_rgb_1[k * 3 + j] = *p2_rgb;
                p2_rgb++;
            }
        }
        p2_rgb = color_rgb_1;   //指针重新指向数组起始位置
        return p2_rgb;
    }

    //这里的功能实现就是使用指针,让两个数组互相赋值
    if(recursion_count % 2 == 0)
    {
        memset(color_rgb_2, 0, sizeof(color_rgb_2));
        for(int i = 0; i < extend_num; i++)
        {
            //正常赋值
            if(i % 2 == 0)
            {
                for(int j = 0; j < 3; j++)
                {
                    color_rgb_2[i * 3 + j] = *p_rgb;
                    p_rgb++;
                }
            }
            //取两个颜色点(r,g,b)的中值再赋值
            else
            {
                r = (*p2_rgb + *(p2_rgb + 3)) / 2;
                g = (*(p2_rgb + 1) + *(p2_rgb + 3 + 1)) / 2;
                b = (*(p2_rgb + 2) + *(p2_rgb + 3 + 2)) / 2;
                color_rgb_2[i * 3] = r;
                color_rgb_2[i * 3 + 1] = g;
                color_rgb_2[i * 3 + 2] = b;
                p2_rgb += 3;
            }
            loop_count++;
        }
        p_rgb = color_rgb_2;    //指针重新指向数组起始位置
    }
    else
    {
        memset(color_rgb_1, 0, sizeof(color_rgb_1));
        for(int i = 0; i < extend_num; i++)
        {
            //正常赋值
            if(i % 2 == 0)
            {
                for(int j = 0; j < 3; j++)
                {
                    color_rgb_1[i * 3 + j] = *p_rgb;
                    p_rgb++;
                }
            }
            //取两个颜色点(r,g,b)的中值再赋值
            else
            {
                r = (*p2_rgb + *(p2_rgb + 3)) / 2;
                g = (*(p2_rgb + 1) + *(p2_rgb + 3 + 1)) / 2;
                b = (*(p2_rgb + 2) + *(p2_rgb + 3 + 2)) / 2;
                color_rgb_1[i * 3] = r;
                color_rgb_1[i * 3 + 1] = g;
                color_rgb_1[i * 3 + 2] = b;
                p2_rgb += 3;
            }
            loop_count++;
        }
        p_rgb = color_rgb_1;    //指针重新指向数组起始位置
    }

    recursion_count++;
    return extendColor(p_rgb, p_rgb, loop_count, recursion_count);      //递归算法的实现

}

三、生成.txt文件储存rgb颜色点

//创建文件(.txt)
void Widget::createFile(int *p_rgb)
{
    char *Edit = 0;
    QString color_rgb;

    //字符串拼接
    for(int i = 1; i <= COLOR_NUM; i++)
    {
        color_rgb += QString::number(*p_rgb);
        if(i == COLOR_NUM)
        {
//            qDebug() << color_rgb;
            break;
        }
        color_rgb += ",";
        //每十个rgb颜色点就换行
        if(i % 30 == 0)
        {
            color_rgb += "\n";
        }
        p_rgb++;
    }

//.txt

    //类型转换
    QByteArray color_rgb_array = color_rgb.toLatin1();
    Edit = color_rgb_array.data();
    //数据长度
    qint64 length = color_rgb.length();

//    QString Filepath = QDir::currentPath();
    QString file_name = "color.txt";


    QFile file(file_name);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text|QIODevice::Append))
    {
        file.write(Edit,length);
        file.close();
        QMessageBox::warning(this,tr("创建文件"),tr("文件创建成功!"));
    //        设置box大小
    //        success.setStyleSheet("QLabel{"
    //                              "min-width: 200px;"
    //                              "min-height: 100px;"
    //                              "}");

    }
    else
    {
       QMessageBox::warning(this,tr("创建文件"),tr("文件创建失败!"));
    }

}

四、补充代码

以上三个是widget.cpp的主要内容,下面把其他文件代码列出。

widget.h如下:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <iostream>
#include <sstream>
#include <QDebug>
#include <QString>
#include <QMessageBox>
#include <QTextStream>
#include <QFileDialog>
#include <QFile>
#include <QColorDialog>

#define COLOR_NUM 256 * 3

using namespace std;

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void changeColor();
    void createFile(int *p_rgb);
    int *extendColor(int *p_rgb, int *p2_rgb, int color_rgb_num, int recursion_count);

private:
    int recursion_count = 0;
    int color_rgb_1[COLOR_NUM];
    int color_rgb_2[COLOR_NUM];

};
#endif // WIDGET_H

main.cpp如下:

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.changeColor();
    return a.exec();
}

五、运行结果

1.程序运行完后会有一个提示框

2.在build文件目录下会生成一个color.txt文件

3.color.txt文件内容如下:

提示:每三个数就是一种颜色,理论上是有256种颜色,但由于有些点的数值相近,所以算出来会有一样的点,也就是该扩展颜色的办法会有一定的误差。

六、补充(均匀采样)

当颜色点超过我们所需的颜色点数(这里是255个),就需要用到均匀采样,这样才能尽量缩小与原来色板的差别,以下方法和过程跟上面有所不同,可参考修改

int Widget::hexToInt(const QString &hexString)
{
    return hexString.toInt(nullptr, 16);
}


QString Widget::rgbToString(int red, int green, int blue)
{
    return QString("%1, %2, %3").arg(red).arg(green).arg(blue).replace(" ", "");
}


void Widget::changeColor()
{
    //提取16进制颜色数据
    QString filePath = "./hex_color.txt"; // 指定文件路径
    QFile file(filePath);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "Failed to open file:" << file.errorString();
        return;
    }

    QStringList allColors; // 存储所有的十六进制数的QStringList

    QTextStream in(&file);
    while (!in.atEnd()) {
        QString line = in.readLine().simplified(); // 读取并去除行末尾的空格
        if (!line.isEmpty() && line.startsWith("#")) {
            allColors.append(line.mid(1)); // 去掉 '#' 符号并添加到列表中
        }
    }

    file.close();

    // 获取均匀采样的255个十六进制数
    int totalColors = allColors.size();
    double step = static_cast<double>(totalColors) / 255.0;
    QString rgbString;

    for (int i = 0; i < 255; ++i) {
        int index = qBound(0, static_cast<int>(i * step), totalColors - 1); // 确保 index 在有效范围内
        QString hexColor = allColors[index];
        int red = hexToInt(hexColor.mid(0, 2));
        int green = hexToInt(hexColor.mid(2, 2));
        int blue = hexToInt(hexColor.mid(4, 2));
        rgbString += rgbToString(red, green, blue);
        if(i != 254)
        {
            rgbString += ",";
        }
    }

    QString filePath_rgb = "./rgb_color.txt"; // 指定要创建的.txt文件路径

    QFile file_rgb(filePath_rgb);
    if (!file_rgb.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qWarning() << "无法创建文件:" << file_rgb.errorString();
        return;
    }

    QTextStream out(&file_rgb);
    out << rgbString;

    file_rgb.close();
}

注意:需要先创建一个hex_color.txt文件,用来存放全部的16进制颜色点,采样后的rgb颜色点会保存在运行目录下的rgb_color.txt文件里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值