1

I have an unsigned char array that is defined like so:

unsigned char **chars = new unsigned char *[H];
for(int i = 0; i < H; i++)
{

    chars[i] = new unsigned char[W*3];
}

Where H is the height of the image, and W is the width, and chars is populated in the rest of that function looping over rows x columns of the input image. Chars is populated in the order Red Green Blue

I am trying to read it with something like this:

QImage *qi = new QImage(imwidth, imheight, QImage::Format_RGB888);
    for (int i = 0 ; i < imheight ; i++)
        for (int j = 0 ; j < imwidth ; j++)
        {      //not sure why, but have to flip j and i in the index for setPixel
               qi->setPixel(j,i,qRgb(imageData[i][j],imageData[i][j+1],imageData[i][j+2]));
               j+=3;

           }

   QPixmap p(QPixmap::fromImage(*qi,Qt::AutoColor));
   QPixmap p1(p.scaled(ui->menuBar->width(),ui->menuBar->width(), Qt::KeepAspectRatio, Qt::SmoothTransformation ));
   ui->viewLabel->setPixmap(p1);
   ui->viewLabel->setFixedHeight(p1.height());
   ui->viewLabel->setFixedWidth(p1.width());

where chars was returned to this calling function in the imageData array.

What am I doing wrong? Should I use a different format, even though I am clearly allocating 3 unsigned chars per pixel (which is why I chose the RGB888 format). This code as posted returns an image, but it is displaying incorrectly - partially scrambled, washed out, etc

Thanks

Derek
  • 11,715
  • 32
  • 127
  • 228
  • I don't see any mention of what exactly is wrong? Crash? Blank image? – Stephen Chu Jan 19 '11 at 01:40
  • I will add the info - the code as in the question gives me the wrong image. It looks scrambled and washed out, but I can see traces of my original image. – Derek Jan 19 '11 at 02:45

1 Answers1

4

You can create a QImage directly from a block of data without copying every pixel.

Since your image is stored with separate rows, you need something like

QImage image = new QImage(width,height,QImage::RGB888)

for (int h=0;h<height;h++) {
    // scanLine returns a ptr to the start of the data for that row
    memcpy(image.scanLine(h),chars[h],width*3);
}

if you use RGB32 then you need to manually set the alpha channel for each pixel to 0xff - just memset() the entire data to 0xff first

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • Even if my array coming in, imageData is 2D? I tried it with something like QImage *qi = new QImage(fullCharArray, imwidth, imheight, QImage::Format_RGB32); where fullCharArray is a "flattened" version of that 2D array, and didnt get any different results. – Derek Jan 19 '11 at 00:37
  • As long as the pixels are contiguous you can just create a QImage, if you have rows with extra padding then copy each row ata time into the QImage buffer - QImage.scanLine(n) gives you a pointer to the destination for row 'n' – Martin Beckett Jan 19 '11 at 00:40
  • I will give it a try - and as for the other question - I am displaying it in a label on my user interface – Derek Jan 19 '11 at 00:50
  • I tried QImage *qi = new QImage(*imageData, imwidth, imheight, QImage::Format_RGB32); and it crashes my application – Derek Jan 19 '11 at 00:59
  • Using your edited code, I was able to get it working. scanline must be the trick – Derek Jan 19 '11 at 15:31
  • There's also QImage.bits() that gives you a pointer to the start of the image data. – Martin Beckett Jan 19 '11 at 15:57