RAW8 pixel format to QImage. A little problem...
-
Hi folks,
I have a return image from a Camera device that I use. The type format is Image (it doesn't matter) and it's pixel format is RAW8.
This is the only way to take full resolution from this camera (4096x2160) and also have some color there. In RGB format I have lower resolution and bad (really very bad -8fps) frame rate.
So I want a good code advice to make it happen.Here is some code from my implementation;
//Image thing just to show you the Format I get Image newImg; error = rawImage.Convert( PIXEL_FORMAT_RAW8, &newImg ); if (error != PGRERROR_OK) { error.PrintErrorTrace(); return false; }
//This is the way I tried (but failed) to take the capture image QImage tmpImg( (uchar *)newImg.GetData(), width, height, width, QImage::Format_Indexed8); (*grabedFrame) = tmpImg.copy();
//I also tried this way but the image I took was in gray-scale, with low frame rate and bad grey // lines (horizontal and vertical) static QVector<QRgb> colorTable; for (int i=0; i<256; i++) colorTable.push_back(qRgb(i,i,i)); // Create QImage with same dimensions as input image QImage tmpImg( (uchar *)newImg.GetData(), width, height, width, QImage::Format_Indexed8); tmpImg.setColorTable(colorTable); (*grabedFrame) = tmpImg.copy(); //with .GetData I take the Image location in memory
-
@codebit thanks for your answer!
It is already in a loop and I've check it before. Each pixel is 8 bit long and (of course) it's values are from 0 to 255 (also checked before).
The QImage class says in http://doc.qt.io/qt-4.8/qimage.html under the "Member Type Documentation" that "Note: Drawing into a QImage with QImage::Format_Indexed8 is not supported" and I think that this is responsible for our problem.
-
I'd say the problem is that data must be 32bit aligned, even if it's a 8bit format. See the constructor:
http://doc.qt.io/qt-4.8/qimage.html#QImage-4
You should align your raw data before passing it to QImage.
-
@Insidious_Snot Your QImage is gray-scaled because you're creating a gray-scale palette in your colorTable. I'm not sure about your original Image class - does it have a palette info you can fetch and use instead of making your own gray-scale one?
-
@Leonardo you are right. But how I do that? Make a QPalette for this and then get the Data. I'm a little confused (and also new in Qt so keep calm with my questions ;)...)
@codebit you think that the way to have a solution is that I said to @Leonardo ?
I think that its to much processing for live image and the fps will slow down :(.
-
@Insidious_Snot, you just need to pad your pixels, so each of them takes 4 bytes. Once I needed to use 24bit RGB data with QImage. Here's what I did:
uchar* output = (uchar*) malloc(width*height*4); int in_size = width*height*3; for(int i = 0 , j = 0 ; i < in_size ; i += 3, j+= 4){ output[j] = input[i]; output[j+1] = input[i+1]; output[j+2] = input[i+2]; output[j+3] = 0; } QImage img(output, width, height, QImage::Format_RGB32, free, output);
If you're doing live processing, maybe you should consider working on the raw data yourself, instead of relying on QImage. Or maybe you could use some more specialized library, like OpenCV.
-
@Insidious_Snot No, QPalette is for the window system. What I'm saying you should look at the documentation of Image::Convert( PIXEL_FORMAT_RAW8, &newImg ) and figure what it creates. Chances are it creates a gray-scaled 8-bit indexed image (in this case your code is right) or it creates a colored 8-bit indexed image in which case it should provide you with the palette that is being used.
We have no clue where this Image class comes from :) -
@codebit the reference for PIXEL_FORMAT_RAW8 at camera's API is;
PIXEL_FORMAT_RAW8 = 0x00400000, /**< 8 bit raw data output of sensor. */
Also full description for Image::Convert(...) is;
* Converts the current image buffer to the specified output format and * stores the result in the specified image. The destination image * does not need to be configured in any way before the call is made. * * @param format Output format of the converted image. * @param pDestImage Destination image. * * @return An Error indicating the success or failure of the function. */ virtual Error Convert( PixelFormat format, Image* pDestImage ) const;
The camera constructor makes clear that I can use it's full resolution only with that pixel format. As I see in the test program that come with the device, the pix format is RAW8 and I have color image.
Forthwith I tried to make the conversion to RGB format (RGB for Camera's API 24bit and RGB888 for Qt) and I have the live image in resolution I want but in very low frame rate which caused by data processing and not from camera setting.
@Leonardo thanks for your help and your code ;). Unfortunately it doesn't works. It appears the image above:
Of course I didn't use your code block unchanged but I made the suitable mods in order to work correctly with the rest code. Take a look here;
uchar* output = (uchar*) malloc(width*height*4); int in_size = width*height*3; int j; for(int i = 0 , j = 0 ; i < in_size ; i += 3, j+= 4) { output[j] = (uchar)newImg[i]; output[j+1] = (uchar)newImg[i+1]; output[j+2] = (uchar)newImg[i+2]; output[j+3] = 0; } (*grabedFrame) = img.copy();```
-
Hi. Since you're using a 8bit image, your input is 1 byte per pixel. So:
uchar* output = (uchar*) malloc(width*height*4); int in_size = width*height; int j; for(int i = 0 , j = 0 ; i < in_size ; i++, j+= 4) { output[j] = (uchar)newImg[i]; output[j+1] = 0; output[j+2] = 0; output[j+3] = 0; }
-
@Leonardo it returns me that now ;
http://bit.ly/1LJPXIouchar* output = (uchar*) malloc(width*height*4); int in_size = width*height; int j; for(int i = 0 , j = 0 ; i < in_size ; i++, j+= 4) { output[j] = (uchar)newImg[i]; output[j+1] = 0; output[j+2] = 0; output[j+3] = 0; } QImage img(output, width, height, QImage::Format_RGB32, free, output); (*grabedFrame) = img.copy();
-
Oh, I see the constructors available for Qt 4.8 are different. The one in my code is for Qt 5.5. I didn't know this one in which you can specify the number of bytes per line. You were right from the start. Your first code should work, according to the documentation.
QImage tmpImg( (uchar *)newImg.GetData(), width, height, width, QImage::Format_Indexed8);
I'm interested in this issue. Would you mind dumping your raw data to a file and posting it here? I'd like to try it later.
-
uchar* output = (uchar*) malloc(width*height*4); int in_size = width*height; int j; for(int i = 0 , j = 0 ; i < in_size ; i++, j+= 4) { output[j] = (uchar)newImg[i]; output[j+1] = 0; output[j+2] = 0; output[j+3] = 0; } QImage img(output, width, height, width, QImage::Format_RGB32, free, output); (*grabedFrame) = img.copy();
And returns me that : http://bit.ly/1L0fHzz
Of course! I would try to get it now...
-
@Leonardo here is the Raw8 data : http://bit.ly/1WtnXMg
I have put spaces and lines in order to make it easier to read. Each line has length == columns/2 (cause the spaces I put).
-
Hi. Well, it's working. Here's what I've done:
QFile f("D:/img.bin"); if(f.open(QIODevice::ReadOnly)){ QByteArray b = f.readAll(); QImage img((const uchar*) b.constData(), 4096, 2160, 4096, QImage::Format_Indexed8); QVector<QRgb> colorTable; for (int i = 0; i < 256; i++){ colorTable.push_back(qRgb(i,i,i)); } img.setColorTable(colorTable); img.save("D:/img.png"); f.close(); }
And here's what I got: