Цветовые каналы меняются с помощью Qt QImage с данными, и я не знаю почему - PullRequest
0 голосов
/ 28 января 2020

Я написал функцию в Qt для извлечения данных из изображения с целью манипулирования им.

Затем у меня есть другая функция, чтобы повторно вставить данные обратно в изображение и отобразить его. Проблема, с которой я столкнулся, заключается в том, что даже если я не выполняю никаких манипуляций с данными пикселей, кроме извлечения и повторной вставки, они все равно изменяют данные. На желтом изображении он меняет его на бирюзовый, когда должен оставаться желтым.

Я включаю код функции для извлечения и повторной вставки в качестве кода образца. Я могу включить больше, если это необходимо, например, функцию отображения и т. Д. c ... Кто-нибудь знает, если я делаю что-то не так?

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    filter = "All Picture Files (*.png *.jpg *.jpeg *.bmp *.tif *.tiff)"
             ";; Bitmap Files (*.bmp) ;; JPEG (*.jpg *.jpeg) ;; PNG (*.png) ;; TIFF (*.tif *.tiff)";
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::importImage()
{
    importCancelled = false;
    QString filename = QFileDialog::getOpenFileName(nullptr, QObject::tr("Import Image"), "", filter);
    if(!filename.isEmpty()){
        image.load(filename);
        image = image.convertToFormat(QImage::Format_RGBA8888);
    }
    else {
        importCancelled = true;
        if(importCancelled){
            QString cleanPlateCancelled = "Operation Cancelled";
            ui->statusBar->showMessage(cleanPlateCancelled,5000);
            return;
           }
    }
}

void MainWindow::scaleImage()
{
    if (image.isNull()){
        return;
    }
    else {
        image = image.scaledToHeight(ui->view->height(), Qt::TransformationMode::SmoothTransformation);
    }
}

void MainWindow::displayImage()
{
    if (image.isNull()){
        return;
    }
    else {
        scene = new QGraphicsScene;
        showImage = new QGraphicsPixmapItem(QPixmap::fromImage(image));
        scene->addItem(showImage);
        ui->view->setScene(scene);
    }
}

void MainWindow::rgbaExtraction()
{
    numberOfBytes = static_cast<uint>(image.sizeInBytes());
    auto const imageData = image.bits();
    rgba = std::vector<uchar>(numberOfBytes,0);
    rgbaReset = std::vector<uchar>(numberOfBytes,0);

    for (uint i{0}; i < numberOfBytes; ++i) {
        rgbaReset[i] = rgba[i] = imageData[i];
    }
}

void MainWindow::rgbaInsertion()
{
    auto *imageData = new uchar[numberOfBytes];
    for (uint i{0};i < numberOfBytes;++i) {
        imageData[i] = rgba[i];
    }
    image = QImage(imageData, image.width(), image.height(), QImage::Format_RGBA8888);
}


void MainWindow::on_importButton_clicked()
{
    importImage();
    scaleImage();
    displayImage();
    rgbaExtraction();
}

void MainWindow::on_quitButton_clicked()
{
    QApplication::quit();
}

void MainWindow::sceneUpdater()
{
    showImage->setPixmap(QPixmap::fromImage(image));
    scene->update();
    ui->view->update();
}

void MainWindow::on_redSlider_valueChanged(int value)
{
    QString redString = QString::number(value);
    ui->redLabel->setText(redString);
    redDelta = value;
    colorRed();
    rgbaInsertion();
    sceneUpdater();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QImage>
#include <QFileDialog>
#include <string>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_importButton_clicked();

    void on_quitButton_clicked();

    void on_redSlider_valueChanged(int value);

private:
    QGraphicsPixmapItem *showImage;
    QGraphicsScene *scene;
    QString filter;
    QImage image;
    bool importCancelled;
    QStatusBar *statusBar;

    uint numberOfBytes;
    std::vector<uchar> rgba;
    std::vector<uchar> rgbaReset;

    int redDelta{0};
    int greenDelta{0};
    int blueDelta{0};
    int opacityDelta{0};

    void importImage();
    void scaleImage();
    void displayImage();
    void rgbaExtraction();
    void rgbaInsertion();
    void sceneUpdater();

    void colorRed();  // Implemented in color.cpp
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

цвет. cpp

#include <mainwindow.h>

void MainWindow::colorRed()
{
    for (uint i{0}; i < rgba.size()*sizeof (rgba[i]);i+=4) {
        if(rgbaReset[i] + static_cast<uchar>(redDelta)>=255){
            rgba[i] = 255;
        }
        else {
            rgba[i] = rgbaReset[i];// + static_cast<uchar>(redDelta);
        }
    }
}

основной. cpp

#include "mainwindow.h"

#include <QApplication>

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

1 Ответ

1 голос
/ 29 января 2020

Проблема в scaleImage(), потому что scaledToHeight() возвращает другой формат изображения. Вы можете опустить операцию масштабирования или преобразовать возвращенное изображение в Format_RGBA8888:

void MainWindow::scaleImage()
{
    if (image.isNull()){
        return;
    }
    else {
        image = image.scaledToHeight(ui->view->height(), Qt::TransformationMode::SmoothTransformation)
                    .convertToFormat(QImage::Format_RGBA8888);
    }
}

. Я рекомендую добавлять некоторые инструменты после каждой манипуляции с изображением, чтобы проверить, что оно имеет ожидаемый формат:

qDebug() << Q_FUNC_INFO << "image format:" << image.format();
...