2017-08-05 7 views
0

reinterpret_cast<uchar*>(quint32*)からQImageコンストラクタを使用してARGB32 QImageを作成しようとすると、イメージはカラーとアルファチャンネルを失い、その結果のQImageはグレースケールです!uint32またはuchar配列からARGB QImageを作成する

グレースケールで表示しようとすると、グレースケールイメージが期待通りに表示されます。だから私はスケーリングとquint32アレイへのushortデータのインデックス作成はうまくいったが、何がうまくいかないのだろうか?

A Qt forum post私はそれをやっているように(私が見る限り)、しかし多分Qtのそのバージョン以来の動作は変わっていますか?

私はドキュメントが言うことを実現(私はQtの5.9を使用しています):

データは32ビットで整列させる必要があり、かつ画像 内のデータのそれぞれの走査線は、32ビットを揃えなければなりません。

しかし、私はquint32がreinterpret_cast<uchar*>()の後でも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) 
    ); 
} 
私はこのような半透明の青色から緑色〜赤色画像を計算(符号なしshort値を持つアレイ)の結果を変換してい

ここで、valは、ushortデータからスケーリングされた0と1の間の倍数です。 (m_pData[i*m_iWidth + j] - lowVal)/(double)winWidthがUSHORTツーダブルスケーリング方法である

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

: 各QRgb値は、このようなquint32配列の対応するインデックスに格納されます。 これはforループで行われます。

は最後に私がイメージを構築しようとすると:

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

しかし、直後に呼び出されたときtmpQImage.allGray() trueを返しますので、私は、期待どおり、これは動作しません!

私は間違っていますが、代わりにARGB画像を作成して色とアルファチャンネルを維持するにはどうすればよいですか?

+0

トラブルシューティングのヒント:2次元のforループとQImageの「putpixel」メソッドを使用してピクセル単位で画像を生成し、その画像がすぐに出力されるかどうかを確認してください。正しい場合は、この正しいイメージの生データとグレースケールイメージのデータを比較します。それが正しいのではない場合、問題は元の生画像データに含まれていなければなりません。 – hyde

答えて

2

問題を再現しようとしましたが、できませんでした。

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

私がコンパイルされ、VS2013、Qt5でそれをテストしました。Windows 10上の6(64ビット):

Snapshot of testQImageGrayToRGB

  1. val_to_機能は私疑わしい少し製:(uchar)にキャスト発現を、その後定数項を加える(これ間違いなくに収まらない場合は、結果はuchar ...
    Hmm ...
    したがって、私はそれらを–少しクリアしますアップアップ。
    実際、視覚的な比較により、差異はほとんど見えないことが示されています(唯一の黄色い領域の赤い線は例外です)。

  2. quint32アレイ(キャストto uchar* -hackを含む)の中でQImageを作ることに問題はありませんでした。


更新:

はしてもよいし、それは明らかにされていません:サンプルコードは慎重に(std::vector<quint32> dataAGAstd::vector<quint32> dataDS)バッファデータの寿命を付与するように設計されてより長いですQt画像の生涯(QImage qImgAGAおよびQImage qImgDS)。これはQtの文書に従って行われています。 QImage::QImage()のために:

バッファが変更またはそうでなければ、元のバッファから切り離されていないQImageとすべてのコピーの寿命を通じて有効でなければなりません。イメージは破壊時にバッファを削除しません。関数ポインタcleanupFunctionと、最後のコピーが破棄されたときに呼び出される余分なポインタcleanupInfoを指定できます。

イメージデータが大量のメモリを消費することがあります。したがって、QImageの実装では、不要なコピー(安全なメモリスペースと時間に対する)を防止しようとしています。代わりに、「ユーザ」(すなわち、アプリケーション開発者)は、画像データの適切な記憶を確保する責任がある。

+0

'quint32 *'ではなく 'tmpData'に' std :: vector ' ありがとうございました。私の色変換の修正もありがとうございました。(赤い線がどこから来たのか分かりませんでした!) –

+0

@AndreasGravgaardAndersenあなたは「バッファはQImageの寿命を通して有効でなければなりません変更されていないか、元のバッファから切り離されているすべてのコピー」と表示されます。 (引用:['QImage :: QImage()'](http://doc.qt.io/qt-5/qimage.html#QImage-3) – Scheff

+0

私は知っていますが、私は完全ではないかもしれませんそれが何を意味するのかを理解する。 '.allGray()'が構築の直後に(コピーや変更を行う前に)trueを返すと、バッファはその時点で有効になると思いましたか?少なくともデバッグモード(VS2015)では。 コンパイル時にいくつかの副作用があるため、QImageの生涯を通じて_文字通り_を取らなければなりませんか? –

関連する問題