With C++ and Qt how do I display a 16-bit raw file as an image?

后端 未结 3 1596
独厮守ぢ
独厮守ぢ 2020-12-20 01:01

I am looking to display heightmaps from the video game Battlefield 2 as images in my application.
I am new to C++ and Qt and it might be straight forward but what I am h

相关标签:
3条回答
  • 2020-12-20 01:19

    1. Basically what you need to do is to draw your pixels inside a widget.

    So, firstly create an application which has a dialog, then draw on the dialog using the recommendations from:

    Qt4 How to draw inside a widget?

    And for the QPainter documentation: http://qt-project.org/doc/qt-4.8/QPainter.html

    Notice, that you will need to create a QBrush while going through the pixels: http://doc.qt.nokia.com/4.7/qbrush.html

    This will be pretty slow :(

    2. Another more advanced solution would be to create a QImageReader and an associated Image IO plugin to read your format ( http://qt-project.org/doc/qt-4.8/qimagereader.html ) then create a QPixMap with the image reader ( http://qt-project.org/doc/qt-4.8/qpixmap.html#fromImageReader ) and create a QBrush with the given QPixmap and use it to draw :)

    0 讨论(0)
  • 2020-12-20 01:22

    Just a guess. Maybe try something like this?

    #include <QColor>
    ...
    QByteArray data=file.readAll();
    
    // create an empty image of the right size.  We'll use 32-bit RGB for simplicity
    QImage img(1025,1025, QImage::Format_RGB32);
    
    // Access the image at low level.  From the manual, a 32-bit RGB image is just a
    // vector of QRgb (which is really just some integer typedef)
    QRgb *pixels=reinterpret_cast<QRgb*>(img.bits());
    
    // Now copy our image data in.  We'll assume 16-bit LE format for the input data.
    // Since we only have 8 bits of grayscale color resolution in a 32-bit RGB, we'll
    // just chop off the most significant 8 bits (the second byte of each pair) and 
    // make a pixel out of that.  If this doesn't work, our assumption might be off --
    // perhaps assume 16-bit BE format.  In that case we'd want the first byte of each
    // pair.
    for (size_t i=0;2*i<data.size();++i)
    {
        uchar pixel_msb=data[2*i+1]; // or maybe try =data[2*i+0]
        pixels[i]=qRgb(pixel_msb, pixel_msb, pixel_msb);
    }
    
    // (do something with the resulting 'img')
    

    edit: oops, QImage::Format_RGB32 instead of QImage::Format_RGB

    0 讨论(0)
  • 2020-12-20 01:31

    You cannot use loadFromData, because it does not support raw (see Reading and Writing Image Files).

    You can't find 16bit raw in supported format so I think the best solution is using a converter between the image loading and the image displaying.

    Create a new QImage, with a format supported by qt.

    QImage* image = new QImage(1025, 1025, QImage::Format_RGB888);
    

    Then load the source image and convert it to RGB888. Your image is very big, so avoid loading it all with readAll(). You can use this simple converter (see below) or a converter from an existing library (like Magick++).

    QFile file("HeightmapPrimary.raw");
    if (!file.open(QFile::ReadOnly))
    {
        qDebug("Could not open file");
        return;
    }
    uint16_t buf;
    uchar* dst = image->bits();
    while (readData(&buf, 2)) {
      dst[0] = buf / 256; /* from 16bit to 8bit */
      dst[1] = buf / 256;
      dst[2] = buf / 256;
      dst += 3; /* next pixel */
    }
    
    0 讨论(0)
提交回复
热议问题