Qt: PNG imagen de transparencia perdido después de la apertura

Estoy tratando de abrir un archivo PNG a usar QT pero el alfa valores de los píxeles es siempre 255 incluso cuando la imagen está en blanco (es decir, el valor de alfa debe ser 0)

He tratado de convertir la imagen a ARGB de formato después de la carga, pero que no ayuda. Aquí está un ejemplo de un espacio en blanco png estoy tratando de cargar:

Imagen:

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

El resultado esperado es 0 0 0 0 pero me da 255 255 255 255

Alguna sugerencia sobre cómo obtener la salida deseada? Gracias de antemano. Estoy usando Qt 5.11.

1 Respuestas

  • Scheff
    4 de mayo de 2019

    Traté de reproducir el problema de la OP.

    Por desgracia, imgur.com está bloqueado en mi empresa. Por lo tanto, empecé con una pequeña muestra de la imagen que he preparado en GIMP.

    Sample Image made in GIMP (8x8, RGBA) ← Es muy pequeño: de 8x8 píxeles con RGBA canales.

    A continuación, hizo una pequeña aplicación de ejemplo para inspeccionar el resultado en un QImagetestQImageRGBA.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)
    {
      // pixel dump code like done by OP
      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;
    }
    

    y Qt archivo de proyecto – testQImageRGBA.pro:

    SOURCES = testQImageRGBA.cc
    
    QT += widgets
    

    Compilado y probado en 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
    

    El volcado refleja exactamente lo que he hecho en GIMP. Por favor, tenga en cuenta los píxeles de las esquinas, que son de color negro transparente.

    He preparado un CMake archivo de origen 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)
    

    y compilado la misma fuente en VS2017. Probado en cmd.exe en 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>
    

    Efectivamente hay ninguna diferencia.


    Una vez en casa (con acceso a imgur.com), he descargado la imagen de OP JGbVc0r.png y lo intentó de nuevo.

    Primero en 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
    

    a continuación, en VS2017 y cmd.exe:

    C:\Users\Scheff\tests\misc\Qt\QImageRGBA>build-VS2017\Debug\testQImageRGBA.exe
    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 declaró:

    El resultado esperado es 0 0 0 0

    y eso es exactamente lo que tengo que hacer.


    repleta proporcionan una interesante pista sobre una trampa sobre QColor::QColor(QRgb), que es el tema de Q/A

    ASÍ: QImage configuración de alfa en PNG con transparencia.

    Sin embargo, llegué a la conclusión de que esto no debería ser el problema aquí porque en el OPs código

    qInfo()<<qRed(img.pixel(p1,p2))<<qBlue(img.pixel(p1,p2))<<qGreen(img.pixel(p1,p2))<<qAlpha(img.pixel(p1,p2));
    

    Por lo tanto, la underhanding QColor::QColor(QRgb) es simplemente que no participan. Para eliminar mis últimas dudas, simplemente he intentado esto en 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
    

    y en VS2017 y cmd.exe:

    C:\Users\Scheff\tests\misc\Qt\QImageRGBA>build-VS2017\Debug\testQImageRGBA.exe
    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
    

    Así que, sencillamente, no puedo reproducir el problema de la OP, aunque me esforcé.

    El OP puede tomar mi código para probar así. Ya sea OP pasado por alto algo que no estaba expuesto en la pregunta o hay un problema específico en la OP del sistema.