如何利用颜色映射表修改QImage全部像素值,实现灰度图转彩色?
解决QImage使用颜色映射表将灰度图转彩色图的问题
你遇到的问题主要有两个核心原因:
- 颜色映射表未初始化:你的
ColorMap对象的computeColorMap()方法从未被调用,导致COLORMAP.inferno是空的,自然无法应用颜色映射。 setColorTable的适用范围限制:QImage的setColorTable()仅对**索引格式(如Format_Indexed8)**的图像生效,而你从网络加载的图片是RGB格式(默认是Format_RGB32或类似),直接调用这个方法不会有任何效果。
下面是修复后的完整方案:
第一步:初始化颜色映射表
在Image的构造函数中添加颜色映射表的初始化代码,确保颜色数据被正确加载:
Image::Image(QQuickItem *parent) : QQuickPaintedItem(parent) { // 先初始化颜色映射表 COLORMAP.computeColorMap(); // 原有的网络加载代码... QJsonObject reponse; QEventLoop event_loop; QImage my_image; QNetworkAccessManager *manager = new QNetworkAccessManager(); QObject::connect(manager, SIGNAL(finished(QNetworkReply *)), &event_loop, SLOT(quit())); QString full_url_request = "https://external-content.duckduckgo.com/iu/" "?u=https%3A%2F%2Fhdwallsbox.com%2Fwallpapers%2Fl%2F750x1334%2F20%" "2Fabstract-patterns-grayscale-artwork-750x1334-19824.jpg&f=1&nofb=1"; const QUrl url_img = QUrl(full_url_request); QNetworkRequest request(url_img); QNetworkReply *reply = manager->get(request); event_loop.exec(); if (reply->isFinished() && reply->error() == QNetworkReply::NoError) { my_image.loadFromData(reply->readAll()); this->current_image = my_image; event_loop.exit(); delete manager; } else { delete manager; } }
第二步:实现颜色映射的两种方案
方案1:转换为索引图后使用颜色表(效率更高)
这种方式利用QImage的索引格式特性,适合处理大尺寸图片,性能更优:
Q_INVOKABLE void Image::applyColorMap() { qDebug() << "apply_color_map"; if (COLORMAP.inferno.isEmpty()) { qDebug() << "Color map is empty!"; return; } // 1. 将当前RGB灰度图转换为Format_Indexed8格式(8位索引图) QImage indexedImage = current_image.convertToFormat(QImage::Format_Indexed8); // 2. 设置颜色映射表(注意颜色表长度要和索引范围匹配,这里是256色) indexedImage.setColorTable(COLORMAP.inferno); // 3. 更新当前图像并刷新界面 current_image = indexedImage; update(); }
方案2:遍历每个像素直接替换RGB值(兼容性更强)
如果需要保留原图像格式,或者处理非8位灰度图,可以直接遍历像素替换颜色值,兼容性更好:
Q_INVOKABLE void Image::applyColorMap() { qDebug() << "apply_color_map"; if (COLORMAP.inferno.isEmpty()) { qDebug() << "Color map is empty!"; return; } // 确保图像是可修改的RGB32格式 QImage mutableImage = current_image.convertToFormat(QImage::Format_RGB32); int width = mutableImage.width(); int height = mutableImage.height(); // 遍历每个像素 for (int y = 0; y < height; ++y) { QRgb *scanLine = reinterpret_cast<QRgb*>(mutableImage.scanLine(y)); for (int x = 0; x < width; ++x) { // 获取灰度值(灰度图的R/G/B值相同,取其中一个即可) int gray = qRed(scanLine[x]); // 确保灰度值在颜色表的索引范围内(0-255) if (gray >= 0 && gray < COLORMAP.inferno.size()) { scanLine[x] = COLORMAP.inferno[gray]; } } } // 更新当前图像并刷新界面 current_image = mutableImage; update(); }
额外注意事项
- 确保你的
inferno-table-byte-0256.csv文件路径正确,文件内容格式需为每行包含索引、R、G、B四个数值(例如0,0,0,4)。 - 如果你的灰度图是16位或更高位深,需要先将灰度值归一化到0-255范围后,再使用颜色表索引。
内容的提问来源于stack exchange,提问作者jdenozi
相关产品推荐
相关产品推荐

