Search code examples
c++qtqimageqt4.8

Creating a QImage from an XBM


Creating a QBitmap from raw data stored in the XBM format, can easily be done like so QBitmap::fromData(width, height, data, QImage::Format_MonoLSB), with data being the raw data of the XBM file.

Now, what if we want to create a QImage this time? Indeed, say we want to create a QImage from the same XBM raw data. One additional constraint though: no QBitmap should be used here, meaning converting a QBitmap to get a QImage would not be an acceptable solution.

I tried QImage(data, width, height, QImage::Format_MonoLSB) but it doesn't produce the proper image since QImage expects bits to be 32-bits aligned, cf. Qt's 4.8 documentation:

QImage::QImage(uchar * data, int width, int height, Format format)
Constructs an image with the given width, height and format, that uses an existing memory buffer, data. The width and height must be specified in pixels, data must be 32-bit aligned, and each scanline of data in the image must also be 32-bit aligned.

The issue is the XBM is 1-bit aligned (not 32-bits aligned), therefore the QImage produced by QImage(data, width, height, QImage::Format_MonoLSB) is garbage (undefined behavior, "random" image).

So, how to create a QImage from the raw data of an XBM?


EDIT: Here's an XBM file with which a QImage should constructed:

#define x_width 66
#define x_height 27
static char x_bits[] = {
   0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, ...
};

Solution

  • Ok, so it turns out that Qt alreay has implemented a simple code that builds a QImage from the raw data of an XBM:

    QImage image(size, monoFormat);
    image.setColor(0, QColor(Qt::color0).rgb());
    image.setColor(1, QColor(Qt::color1).rgb());
    
    // Need to memcpy each line separatly since QImage is 32bit aligned and
    // this data is only byte aligned...
    int bytesPerLine = (size.width() + 7) / 8;
    for (int y = 0; y < size.height(); ++y)
    {
       memcpy(image.scanLine(y), bits + bytesPerLine * y, bytesPerLine);
    }
    

    This code is used in qbitmap.cpp, more specifically in:
    QBitmap::fromData(const QSize &size, const uchar *bits, QImage::Format monoFormat)