Qt: прозрачность изображения PNG теряется после открытия - PullRequest
0 голосов
/ 03 мая 2019

Я пытаюсь открыть изображение в формате PNG, используя QT, но значения альфа для пикселей всегда равны 255, даже если изображение пустое (т. Е. Значение альфа должно быть 0)

Я пытался преобразоватьизображение в формат ARGB после загрузки, но это не помогло.Вот пример пустого png, который я пытаюсь загрузить:

Изображение:

enter image description here

QImage im = QImage("JGbVc0r.png");
int p1 = 20;
int p2 = 20;
QImage img = im.convertToFormat(QImage::Format_ARGB32);
qInfo()<<qRed(img.pixel(p1,p2))<<qBlue(img.pixel(p1,p2))<<qGreen(img.pixel(p1,p2))<<qAlpha(img.pixel(p1,p2));

Ожидаемый результат0 0 0 0, но я получаю 255 255 255 255

Любые предложения о том, как получить желаемый результат?Заранее спасибо.Я использую Qt 5.11.

1 Ответ

3 голосов
/ 04 мая 2019

Я пытался воспроизвести проблему ОП.

К сожалению, imgur.com заблокирован в моей компании (где я впервые наткнулся на этот вопрос). Поэтому я начал с небольшого образца изображения, которое я подготовил самостоятельно в GIMP.

Sample Image made in GIMP (8x8, RGBA) & larr; Это действительно маленький: 8x8 пикселей с каналами RGBA.

Затем я сделал небольшой пример приложения для проверки результатов в QImage & ndash; 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 & ndash; 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. Протестировано в cmd.exe на Windows 10:

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

ОП указано:

Ожидаемый вывод: 0 0 0 0

и это именно то, что я получил.


replete предоставил интересную подсказку о ловушке, касающейся QColor::QColor(QRgb), которая является предметом Q / A

SO: QImage установка альфа в PNG с прозрачностью .

Тем не менее, я пришел к выводу, что это не должно быть проблемой здесь, потому что в коде OP

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

Итак, я просто не могу воспроизвести проблему ОП, хотя я очень старался.

ОП может также принять мой код для тестирования. Либо ОП пропустил что-то еще, что не было подвергнуто сомнению, либо есть особая проблема в системе ОП.


Моей последней (отчаянной) идеей было проверить, что произойдет, если 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

Порядок вывода немного изменился. Кроме того, я даже получил те же «произвольные» значения (что, имхо, ничего не значит).

...