簡體   English   中英

從uint32或uchar數組創建ARGB QImage

[英]Creating ARGB QImage from uint32 or uchar array

當我嘗試使用QImage構造函數從reinterpret_cast<uchar*>(quint32*)創建ARGB32 QImage時,Image松開其顏色和Alpha通道,得到的QImage是灰度的!

如果試圖將其顯示為灰度,則灰度圖像將按預期顯示。 因此,我知道將ushort數據縮放和索引到quint32數組的操作很順利,但是出了什么問題?

一個Qt論壇帖子建議按照我做的方式來做(據我所知),但是自從那個版本的Qt以來,行為可能已經改變了嗎? (我正在使用Qt 5.9)

我意識到該文檔說:

數據必須是32位對齊的,並且圖像中每個數據掃描線也必須是32位對齊的。

但是即使在reinterpret_cast<uchar*>()之后,我也希望quint32是32位對齊的?

現在是詳細信息:我將計算結果(具有無符號短值的數組)轉換為半透明的藍到綠到紅圖像,如下所示:

inline uchar val_to_blue(const double val) {
    if (val > 0.5)
        return 0;
    else if (val < 0.25)
        return 255;
    else // x={.5,...,.25}:a=255/(.25-.5)=-4*255 & b=-255*0.5/(0.25-0.5)=4/2*255=2*255 
        return (uchar)(val * -4.0 * 255.0) + 2 * 255;
}

inline uchar val_to_green(const double val) {
    if (val > 0.25 && val < 0.75)
        return 255;
    else if (val < 0.25)// x={0,...,.25}:a=255/(.25-0)=4*255 & b=-255*0/(0.25-0)=0 
        return (uchar)(val * 4.0 * 255.0);
    else // if (val > .75) // x={.75,...,1}:a=255/(.75-.5)=4*255 & b=-255*0.5/(0.75-0.5)=-4/2*255=-2*255 
        return (uchar)(val * -4.0 * 255.0) - 2 * 255;
}

inline uchar val_to_red(const double val) {
    if (val < 0.5)
        return 0;
    if (val > 0.75)
        return 255;
    else // x={0.5,...,0.75}:a=255/(0.75-0.5)=4*255 & b=-255*0.5/(0.75-0.5)=-4/2*255=-2*255 
        return (uchar)(val * 4.0 * 255.0) - 2 * 255;
}

inline QRgb val_to_rgba_scale(const double val) {
    return qRgba( // ax+b={0,...,255} for x={i,...,j}, a=255/(j-i), b= -255i/(j-i)
        val_to_blue(val),
        val_to_green(val),
        val_to_red(val),
        (uchar)(val * 81)
    );
}

其中val是從ushort數據縮放的介於0和1之間的雙精度數。 每個QRgb值存儲在quint32數組的相應索引處,如下所示:

if (m_pData[i*m_iWidth + j] >= uppVal)
    tmpData[tmpIdx] = 0x45ff0000;
else if (m_pData[i*m_iWidth + j] <= lowVal)
    tmpData[tmpIdx] = 0x00000000;
else
    tmpData[tmpIdx] = val_to_rgba_scale((m_pData[i*m_iWidth + j] - lowVal) / (double)winWidth);

其中(m_pData[i*m_iWidth + j] - lowVal) / (double)winWidth是從ushort到double的縮放方法。 這是在for循環中完成的。

最后,我嘗試使用以下方法構建圖像:

QImage tmpQImage = QImage(reinterpret_cast<unsigned char*>(tmpData), m_iWidth, m_iHeight, QImage::Format_ARGB32);

但是,這不符合我的預期,因為tmpQImage.allGray()在調用之后立即返回true!

我在做什么錯,應該怎么做才能創建ARGB圖像並保留顏色和Alpha通道?

我試圖重現您的問題,但無法。

OP的實際問題不是所提供代碼的一部分,或者當我嘗試從OP組成MCVE時,我無意中錯過了一個細節。

但是,我想介紹一下我所得到的,因為這可能有助於修復OP。

我的來源testQImageGrayToRGB.cc

#include <vector>

#include <QtWidgets>

typedef unsigned char uchar;

namespace AGA {

uchar val_to_blue(const double val) {
  if (val > 0.5)
    return 0;
  else if (val < 0.25)
    return 255;
  else // x={.5,...,.25}:a=255/(.25-.5)=-4*255 & b=-255*0.5/(0.25-0.5)=4/2*255=2*255 
    return (uchar)(val * -4.0 * 255.0) + 2 * 255;
}

uchar val_to_green(const double val) {
  if (val > 0.25 && val < 0.75)
    return 255;
  else if (val < 0.25)// x={0,...,.25}:a=255/(.25-0)=4*255 & b=-255*0/(0.25-0)=0 
    return (uchar)(val * 4.0 * 255.0);
  else // if (val > .75) // x={.75,...,1}:a=255/(.75-.5)=4*255 & b=-255*0.5/(0.75-0.5)=-4/2*255=-2*255 
    return (uchar)(val * -4.0 * 255.0) - 2 * 255;
}

uchar val_to_red(const double val) {
  if (val < 0.5)
    return 0;
  if (val > 0.75)
    return 255;
  else // x={0.5,...,0.75}:a=255/(0.75-0.5)=4*255 & b=-255*0.5/(0.75-0.5)=-4/2*255=-2*255 
    return (uchar)(val * 4.0 * 255.0) - 2 * 255;
}

} // namespace AGA

namespace DS {

uchar val_to_blue(const double val)
{
  return val < 0.25 ? 255
    : val < 0.5 ? (0.5 - val) * 4 * 255
    : 0;
}

uchar val_to_green(const double val)
{
  return val < 0.25 ? val * 4 * 255
    : val < 0.75 ? 255
    : (1.0 - val) * 4 * 255;
}

uchar val_to_red(const double val)
{
  return val < 0.5 ? 0
    : val < 0.75 ? (val - 0.5) * 4 * 255
    : 255;
}

} // namespace DS

std::vector<quint32> buildImageData(
  const int w, const int h,
  uchar (*pFuncValToR)(double),
  uchar (*pFuncValToG)(double),
  uchar (*pFuncValToB)(double))
{
  // make temp. buffer to build up raw image data
  std::vector<quint32> data(w * h);
  // fill raw image - make values 0 ... 1 in n steps
  const int n = w - 1;
  for (int x = 0; x < w; ++x) {
    const double v = (double)x / n;
    QRgb qRgb = qRgba(pFuncValToR(v), pFuncValToG(v), pFuncValToB(v), 255);
    for (int y = 0; y < h; ++y) data[y * w + x] = qRgb;
  }
  // done
  return data;
}

int main(int argc, char **argv)
{
  qDebug() << "Qt Version: " << QT_VERSION_STR;
  QApplication app(argc, argv);
  // build contents
  enum { w = 256, h = 32 };
  std::vector<quint32> dataAGA = buildImageData(w, h,
    &AGA::val_to_red, &AGA::val_to_green, &AGA::val_to_blue);
  QImage qImgAGA((const uchar*)dataAGA.data(), w, h, QImage::Format_ARGB32);
  std::vector<quint32> dataDS = buildImageData(w, h,
    &DS::val_to_red, &DS::val_to_green, &DS::val_to_blue);
  QImage qImgDS((const uchar*)dataDS.data(), w, h, QImage::Format_ARGB32);
  // build some GUI
  QWidget win;
  QVBoxLayout qVBox;
  QLabel qLblAGA(
    QString::fromUtf8("QImage (Functions of Andreas Gravgaard Andersen):"));
  qVBox.addWidget(&qLblAGA);
  QLabel qLblImgAGA;
  qLblImgAGA.setPixmap(QPixmap::fromImage(qImgAGA));
  qVBox.addWidget(&qLblImgAGA);
  QLabel qLblDS(
    QString::fromUtf8("QImage (Functions of Scheff):"));
  qVBox.addWidget(&qLblDS);
  QLabel qLblImgDS;
  qLblImgDS.setPixmap(QPixmap::fromImage(qImgDS));
  qVBox.addWidget(&qLblImgDS);
  win.setLayout(&qVBox);
  win.show();
  // exec. application
  return app.exec();
}

我在Windows 10(64位)上使用VS2013,Qt5.6對其進行了編譯和測試:

testQImageGrayToRGB的快照

筆記:

  1. val_to_函數讓我有點懷疑:將表達式val_to_轉換為(uchar) ,然后添加一個常數項(絕對不適合(uchar) ,結果返回為uchar ...
    嗯...
    因此,我做了一些清理-對其進行了重新制作。
    實際上,視覺比較顯示差異幾乎是看不見的(唯一的例外是黃色區域中的紅線)。

  2. 我可以使用原始quint32數組(包括quint32uchar* -hack)制作QImage沒問題。


更新:

可能不是很明顯:示例代碼經過精心設計,可以使緩沖區數據( std::vector<quint32> dataAGAstd::vector<quint32> dataDS )的生存期長於緩沖區數據的生存期。 Qt圖像( QImage qImgAGAQImage qImgDS )。 這是根據Qt文檔完成的。 對於QImage::QImage()

緩沖區在QImage整個生命周期內必須保持有效,並且所有未經修改或以其他方式與原始緩沖區分離的副本都必須保持有效。 映像不會刪除銷毀的緩沖區。 您可以提供一個函數指針cleanupFunction以及一個額外的指針cleanupInfo ,該指針將在銷毀最后一個副本時被調用。

圖像數據可能會消耗大量內存。 因此, QImage實現試圖防止不必要的復制(以確保安全的存儲空間和時間)。 相反,“用戶”(即應用程序開發人員)負責確保正確存儲圖像數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM