简体   繁体   中英

How can I change the whole QImage pixel value using a color map?

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:

  • need to download inferno256 inferno color map and change the PATH_INFERNO_COLORMAP in ColorMap.h

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
        }
    }
}

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM