1

I'm writing an image library from scratch I have written a console application that loads a bitmap image does some manipulation and writes the output to another bitmap. Now I would like to build a UI on top of my application. So I would like to do this in Qt Creator since I have some experience with Qt and I want it to work for multiple platforms.

Here is my code that loads a bitmap:

FILE *streamIn = fopen("path/to/file.bmp", "rb");

if (streamIn == (FILE *)0)
{
  printf("Unable to open file\n");
}

unsigned char bmpHeader[54];
unsigned char bmpColorTable[1024];

for (int i = 0; i < 54; i++)
{
  bmpHeader[i] = getc(streamIn);
}

int width = *(int *)&bmpHeader[18];
int height = *(int *)&bmpHeader[22];
int bitDepth = *(int *)&bmpHeader[28];

if (bitDepth <= 8)
{
  fread(bmpColorTable, sizeof(unsigned char), 1024, streamIn);
}
unsigned char buf[height * width];
fread(buf, sizeof(unsigned char), (height * width), streamIn);
fclose(streamIn);

How do I get this into my UI? I already tried something like:

const QImage image(buf, width, height, QImage::Format_Grayscale8);
imageLabel->setPixmap(QPixmap::fromImage(image));

But that results in a tiny white image not the image I just read. Perhaps I can skip creating a QImage and create a QPixmap right away? What I tried now does not work so maybe someone more experienced can tell me how to get it done. When I loaded the initial image I would like to update the view when I do some manipulation so the user can see the changes.

I know it can be done much easier with QImageReader but this is for learning purposes.

Dimitry Ernot
  • 6,256
  • 2
  • 25
  • 37
Smek
  • 1,158
  • 11
  • 33
  • Could you include the sample BMP you're trying to read? This would enable others to reproduce your results. This code won't work if it's compressed. Is it definitely Grayscale8? Incidentally, why do you use a loop to read the header character by character instead of a single fread, as you do below with the pixel data? –  May 21 '19 at 23:58
  • Instead of using the QImage constructor accepting `const uchar *buf` you could read the whole file into memory and use `QImage::loadFromData()` or `QImage(QString filename)`. If this returns a different result your parsing of the header or your data interpretation is wrong / incomplete. – Martin Hennings May 22 '19 at 10:45
  • Hi replete here is a link to an example file: Here's a link to an example image: https://filebin.net/bny9bepzt06h45l4 – Smek May 22 '19 at 18:45
  • Hi Martin, I'm iterating over every value in the buffer and then add it to the image like this: int color = (int)_imgInBuffer[row * img.width() + col]; img.setPixel(col, row, qRgb(color, color, color)); And that works so I do have all the pixel info in the buffer. But I hope to find an easier way to display the data. I changed the format to Format_RGB444. Since the image is a grayscale image I set every channel to the same value. – Smek May 22 '19 at 18:54

1 Answers1

1

I don't know what I did wrong but now it just works like it should. But there is one issue with reading the bitmap format like this in the QImage see Why are bmps stored upside down?

So what I do now is this:

QImage img(width, height, QImage::Format_Grayscale8);
for (int row = 0; row < img.height(); row++) {
    for(int col = 0; col < img.width(); col++) {
        int color = (int)_imgInBuffer[row * img.width() + col];
        img.setPixel(col, height - row - 1, qRgb(color, color, color));
    }
}

I don't know why I need to set a red, green, blue value to a grayscale image but this is the only way to get it done.

Kevin Cox
  • 3,080
  • 1
  • 32
  • 32
Smek
  • 1,158
  • 11
  • 33