目录
最近需要使用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文件里。