我试图重现 OP 的问题。
不幸的是,imgur.com 在我的公司被屏蔽(我是在这个问题上偶然发现的)。因此,我从自己在 GIMP 中准备的小样本图像开始。
← 真的很小:8x8 像素,RGBA 通道。
接下来,我制作了一个小示例应用程序来检查QImage - testQImageRGBA.cc 中的结果:
#include <iomanip>
#include <iostream>
#include <QtWidgets>
void dump(
const QImage &qImg, int row, int col,
std::function<void(const QImage&, int, int)> dumpPixel)
{
qDebug() << qImg;
const int nR = qImg.height(), nC = qImg.width();
const int iR0 = row >= 0 ? row : 0;
const int iRN = row >= 0 ? row + 1 : nR;
const int iC0 = col >= 0 ? col : 0;
const int iCN = col >= 0 ? col + 1 : nC;
std::cout << "Dump of rows [" << iR0 << ", " << iRN << "),"
<< " cols [" << iC0 << ", " << iCN << ")\n"
<< "Pixel format: '#RRGGBBAA'\n";
for (int iR = iR0; iR < iRN; ++iR) {
for (int iC = iC0; iC < iCN; ++iC) {
dumpPixel(qImg, iR, iC);
}
std::cout << '\n';
}
}
int main(int argc, char **argv)
{
std::function<void(const QImage&, int, int)> dumpPixelOP // OPs flavor
= [](const QImage &qImg, int iR, int iC) {
std::cout << std::hex << "_#"
<< std::setw(2) << std::setfill('0') << qRed(qImg.pixel(iC, iR))
<< std::setw(2) << std::setfill('0') << qGreen(qImg.pixel(iC, iR))
<< std::setw(2) << std::setfill('0') << qBlue(qImg.pixel(iC, iR))
<< std::setw(2) << std::setfill('0') << qAlpha(qImg.pixel(iC, iR));
};
std::function<void(const QImage&, int, int)> dumpPixel // my flavor
= [](const QImage &qImg, int iR, int iC) {
const QColor pixel = qImg.pixelColor(iC, iR);
std::cout << std::hex << " #"
<< std::setw(2) << std::setfill('0') << pixel.red()
<< std::setw(2) << std::setfill('0') << pixel.green()
<< std::setw(2) << std::setfill('0') << pixel.blue()
<< std::setw(2) << std::setfill('0') << pixel.alpha();
};
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
const QStringList args = app.arguments();
const QString filePath = args.size() > 1 ? args[1] : "smiley.8x8.rgba.png";
const int row = args.size() > 2 ? args[2].toInt() : -1;
const int col = args.size() > 3 ? args[3].toInt() : -1;
const bool useDumpOP = args.size() > 4;
QImage qImg(filePath);
qImg = qImg.convertToFormat(QImage::Format_ARGB32);
dump(qImg, row, col, useDumpOP ? dumpPixelOP : dumpPixel);
return 0;
}
还有一个 Qt 项目文件——testQImageRGBA.pro:
SOURCES = testQImageRGBA.cc
QT += widgets
在cygwin64中编译测试:
$ qmake-qt5 testQImageRGBA.pro
$ make && ./testQImageRGBA
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQImageRGBA.o testQImageRGBA.cc
g++ -o testQImageRGBA.exe testQImageRGBA.o -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
Qt Version: 5.9.4
QImage(QSize(8, 8),format=5,depth=32,devicePixelRatio=1,bytesPerLine=32,byteCount=256)
Dump of rows [0, 8), cols [0, 8)
Pixel format: '#RRGGBBAA'
#00000000 #00000000 #000000ff #000000ff #000000ff #000000ff #00000000 #00000000
#00000000 #000000ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #000000ff #00000000
#000000ff #ffff00ff #0000ffff #ffff00ff #ffff00ff #0000ffff #ffff00ff #000000ff
#000000ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #000000ff
#000000ff #ffff00ff #ff0000ff #ffff00ff #ffff00ff #ff0000ff #ffff00ff #000000ff
#000000ff #ffff00ff #ffff00ff #ff0000ff #ff0000ff #ffff00ff #ffff00ff #000000ff
#00000000 #000000ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #000000ff #00000000
#00000000 #00000000 #000000ff #000000ff #000000ff #000000ff #00000000 #00000000
转储准确地反映了我在 GIMP 中绘制的内容。请注意黑色透明的角落像素。
我准备了一个CMake源文件CMakeLists.txt:
project(QImageRGBA)
cmake_minimum_required(VERSION 3.10.0)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
find_package(Qt5Widgets CONFIG REQUIRED)
include_directories("${CMAKE_SOURCE_DIR}")
add_executable(testQImageRGBA testQImageRGBA.cc)
target_link_libraries(testQImageRGBA Qt5::Widgets)
并在 VS2017 中编译了相同的源代码。在 Windows 10 上的 cmd.exe 中测试:
C:\Users\Scheff\tests\misc\Qt\QImageRGBA>set PATH=%PATH%;D:\Scheff\Qt\5.11.2\msvc2017_64\bin;$(LocalDebuggerEnvironment)
C:\Users\Scheff\tests\misc\Qt\QImageRGBA>build-VS2017\Debug\testQImageRGBA.exe
Qt Version: 5.11.2
QImage(QSize(8, 8),format=5,depth=32,devicePixelRatio=1,bytesPerLine=32,sizeInBytes=256)
Dump of rows [0, 8), cols [0, 8)
Pixel format: '#RRGGBBAA'
#00000000 #00000000 #000000ff #000000ff #000000ff #000000ff #00000000 #00000000
#00000000 #000000ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #000000ff #00000000
#000000ff #ffff00ff #0000ffff #ffff00ff #ffff00ff #0000ffff #ffff00ff #000000ff
#000000ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #000000ff
#000000ff #ffff00ff #ff0000ff #ffff00ff #ffff00ff #ff0000ff #ffff00ff #000000ff
#000000ff #ffff00ff #ffff00ff #ff0000ff #ff0000ff #ffff00ff #ffff00ff #000000ff
#00000000 #000000ff #ffff00ff #ffff00ff #ffff00ff #ffff00ff #000000ff #00000000
#00000000 #00000000 #000000ff #000000ff #000000ff #000000ff #00000000 #00000000
C:\Users\Scheff\tests\misc\Qt\QImageRGBA>
实际上没有区别。
有一次在家(可以访问 imgur.com),我下载了 OP JGbVc0r.png 的图像并再次尝试。
cygwin64中的第一个:
$ make && ./testQImageRGBA JGbVc0r.png 20 20
make: Nothing to be done for 'first'.
Qt Version: 5.9.4
QImage(QSize(1000, 1000),format=5,depth=32,devicePixelRatio=1,bytesPerLine=4000,byteCount=4000000)
Dump of rows [20, 21), cols [20, 21)
Pixel format: '#RRGGBBAA'
#00000000
然后在 VS2017 和cmd.exe:
C:\Users\Scheff\tests\misc\Qt\QImageRGBA>build-VS2017\Debug\testQImageRGBA.exe JGbVc0r.png 20 20
Qt Version: 5.11.2
QImage(QSize(1000, 1000),format=5,depth=32,devicePixelRatio=1,bytesPerLine=4000,sizeInBytes=4000000)
Dump of rows [20, 21), cols [20, 21)
Pixel format: '#RRGGBBAA'
#00000000
OP 声明:
预期输出为 0 0 0 0
这正是我得到的。
replete 提供了一个有趣的提示,关于一个关于 QColor::QColor(QRgb) 的陷阱,这是 Q/A 的主题
SO: QImage setting alpha in PNG with transparency.
但是,我得出的结论是,这不应该是这里的问题,因为在 OPs 代码中
qInfo()<<qRed(img.pixel(p1,p2))<<qBlue(img.pixel(p1,p2))<<qGreen(img.pixel(p1,p2))<<qAlpha(img.pixel(p1,p2));
因此,不法分子QColor::QColor(QRgb) 根本不涉及。为了消除我最后的疑虑,我在 cygwin 中也简单地尝试了这个:
$ make && ./testQImageRGBA JGbVc0r.png 20 20 dumpLikeOP
make: Nothing to be done for 'first'.
Qt Version: 5.9.4
QImage(QSize(1000, 1000),format=5,depth=32,devicePixelRatio=1,bytesPerLine=4000,byteCount=4000000)
Dump of rows [20, 21), cols [20, 21)
Pixel format: '#RRGGBBAA'
_#00000000
在 VS2017 和 cmd.exe:
C:\Users\Scheff\tests\misc\Qt\QImageRGBA>build-VS2017\Debug\testQImageRGBA.exe JGbVc0r.png 20 20 dumpLikeOP
Qt Version: 5.11.2
QImage(QSize(1000, 1000),format=5,depth=32,devicePixelRatio=1,bytesPerLine=4000,sizeInBytes=4000000)
Dump of rows [20, 21), cols [20, 21)
Pixel format: '#RRGGBBAA'
_#00000000
所以,虽然我很努力,但我根本无法重现 OP 的问题。
OP 也可能会使用我的代码进行测试。要么 OP 忽略了其他未公开的问题,要么 OP 的系统存在特定问题。
我最后一个(绝望的)想法是检查如果 QImage 根本没有加载(例如由于找不到文件)会发生什么。
在 cygwin 中:
$ make && ./testQImageRGBA ImageNotFound.png 20 20
make: Nothing to be done for 'first'.
Qt Version: 5.9.4
QImage(null)
Dump of rows [20, 21), cols [20, 21)
Pixel format: '#RRGGBBAA'
QImage::pixelColor: coordinate (20,20) out of range
#000000ff
$ make && ./testQImageRGBA ImageNotFound.png 20 20 dumpLikeOP
make: Nothing to be done for 'first'.
Qt Version: 5.9.4
QImage(null)
Dump of rows [20, 21), cols [20, 21)
Pixel format: '#RRGGBBAA'
QImage::pixel: coordinate (20,20) out of range
QImage::pixel: coordinate (20,20) out of range
QImage::pixel: coordinate (20,20) out of range
QImage::pixel: coordinate (20,20) out of range
_#00303900
请注意,超出范围的访问会在控制台上通知。除此之外,代码似乎运行正常,但返回任意值。
在 VS2017/cmd.exe:
C:\Users\Scheff\tests\misc\Qt\QImageRGBA>build-VS2017\Debug\testQImageRGBA.exe ImageNotFound.png 20 20
Qt Version: 5.11.2
QImage(null)
Dump of rows [20, 21), cols [20, 21)
Pixel format: '#RRGGBBAA'
QImage::pixelColor: coordinate (20,20) out of range
#000000ff
C:\Users\Scheff\tests\misc\Qt\QImageRGBA>build-VS2017\Debug\testQImageRGBA.exe ImageNotFound.png 20 20 dumpLikeOP
Qt Version: 5.11.2
QImage(null)
Dump of rows [20, 21), cols [20, 21)
Pixel format: '#RRGGBBAA'
_#QImage::pixel: coordinate (20,20) out of range
00QImage::pixel: coordinate (20,20) out of range
30QImage::pixel: coordinate (20,20) out of range
39QImage::pixel: coordinate (20,20) out of range
00
输出顺序发生了一些变化。除此之外,我什至得到了相同的“任意”值(恕我直言,这毫无意义)。