Reputation: 222
I'm looking for a way to change the value of the pixel by another one. My idea is to change a greyscale colour into a colour image using predefined colour maps like inferno found in csv format here (http://www.kennethmoreland.com/color-advice/). Firstly I get the value in the csv and store it as a Qvector then I tried to use it.
I've seen that we can use setColorMap but it's not working.
Here is a full reproducible example:
ColorMap.h
#ifndef COLORMAP_H
#define COLORMAP_H
#include <QDebug>
#include <QFile>
#include <QRgb>
#include <QTextStream>
#include <QVector>
const QString PATH_INFERNO_COLORMAP =
"~/Documents/colormap/inferno-table-byte-0256.csv";
struct ColorMap {
QVector<QRgb> inferno;
void computeColorMap() {
QFile file(PATH_INFERNO_COLORMAP);
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "ERROR: can't open inferno color map";
}
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
QStringList values = line.split(",");
inferno.append(
qRgb(values[1].toInt(), values[2].toInt(), values[3].toInt()));
}
file.close();
}
};
#endif // COLORMAP_H
image.h
#ifndef IMAGE_H
#define IMAGE_H
#include "ColorMap.h"
#include <QImage>
#include <QPainter>
#include <QQuickItem>
#include <QQuickPaintedItem>
class Image : public QQuickPaintedItem {
Q_OBJECT
Q_PROPERTY(QImage image READ image WRITE setImage NOTIFY imageChanged)
public:
Image(QQuickItem *parent = nullptr);
Q_INVOKABLE void setImage(const QImage &image);
Q_INVOKABLE void applyColorMap();
void paint(QPainter *painter);
QImage image() const;
signals:
void imageChanged();
private:
QImage current_image;
ColorMap COLORMAP;
};
#endif // IMAGE_H
image.cpp
#include "image.h"
#include <QImage>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QQmlApplicationEngine>
Image::Image(QQuickItem *parent) : QQuickPaintedItem(parent) {
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;
}
}
void Image::paint(QPainter *painter) {
QRectF bounding_rect = boundingRect();
QImage scaled = this->current_image.scaledToHeight(bounding_rect.height());
QPointF center = bounding_rect.center() - scaled.rect().center();
if (center.x() < 0)
center.setX(0);
if (center.y() < 0)
center.setY(0);
painter->drawImage(center, scaled);
}
QImage Image::image() const { return this->current_image; }
void Image::setImage(const QImage &image) {
this->current_image = image;
update();
}
Q_INVOKABLE void Image::applyColorMap() {
qDebug() << "apply_color_map";
current_image.setColorTable(
COLORMAP.inferno); // COLOR_MAP is an attribute of type
update();
}
main.cpp
#include "image.h"
#include <QGuiApplication>
#include <QImage>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[]) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
qmlRegisterType<Image>("MyImage", 1, 0, "MyImage");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(
&engine, &QQmlApplicationEngine::objectCreated, &app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import MyImage 1.0
import QtQuick.Controls 2.15
import QtQuick.Extras 1.4
Window {
id: window
width: 400
height: 480
visible: true
Rectangle{
id: background
color: "black"
width: parent.width
height: parent.height
anchors.fill: parent
}
Button {
id: button
text: qsTr("Apply color map")
anchors.left: parent.horizontalCenter
anchors.right: parent.horizontalCenter
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.leftMargin: -99
anchors.rightMargin: -99
anchors.topMargin: 8
anchors.bottomMargin: 432
width : 40
height: 20
onClicked: {
my_image.applyColorMap();
}
}
Item {
id: item1
y: 67
height: 413
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 0
anchors.leftMargin: 0
MyImage{
id: my_image
height: parent.height
width: parent.width
}
}
}
Upvotes: 0
Views: 650
Reputation: 10077
Before applying a color table, be sure to have an indexed image, otherwise convert it to the desired format:
if(current_image.format() != QImage::Format_Indexed8)
{
current_image = current_image.convertToFormat(QImage::Format_Indexed8);
}
current_image.setColorTable(
COLORMAP.inferno); // COLOR_MAP is an attribute of type
Not sure about what you're trying to achieve, but I guess the original image should be in 8-bit grayscale format, so maybe, you can check that, first:
if(current_image.format() != QImage::Format_Grayscale8)
{
current_image = current_image.convertToFormat(QImage::Format_Grayscale8);
}
Upvotes: 1