使用带有数据的 Qt QImage 颜色通道正在发生变化,我不知道为什么
Color channels are changing using Qt QImage with data and I don't know why
我在 Qt 中编写了一个函数来从图像中提取数据以进行操作。
然后我有另一个功能将数据重新插入图像并显示它。我遇到的问题是,即使我除了提取和重新插入之外没有对像素数据进行任何操作,它仍在更改数据。在黄色图像上,当它应该保持黄色时,它会将其更改为绿松石蓝色。
我包括提取和重新插入的功能代码作为样本代码。如果需要,我可以包含更多内容,例如显示功能等...有人知道我做错了什么吗?
#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
color.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);
}
}
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
问题出在scaleImage()
,因为scaledToHeight()
returns另一种图像格式。您可以省略缩放操作,或者将返回的图像转换为 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();
我在 Qt 中编写了一个函数来从图像中提取数据以进行操作。
然后我有另一个功能将数据重新插入图像并显示它。我遇到的问题是,即使我除了提取和重新插入之外没有对像素数据进行任何操作,它仍在更改数据。在黄色图像上,当它应该保持黄色时,它会将其更改为绿松石蓝色。
我包括提取和重新插入的功能代码作为样本代码。如果需要,我可以包含更多内容,例如显示功能等...有人知道我做错了什么吗?
#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
color.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);
}
}
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
问题出在scaleImage()
,因为scaledToHeight()
returns另一种图像格式。您可以省略缩放操作,或者将返回的图像转换为 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();