Qt - steps to using QOpenGLWidget to display images - qt

I'm trying to use a QOpenGLWidget to show some images instead of using QLabel. But I'm a bit confused about how to do this.
To make the widget get the job done, I know I need to reimplement the initializeGL() method and paintGL() method.
To get the texture of an image, what I used is SOIL_load_image(). Why is unsigned char* img_data over unsigned char* img_data[3]? I think each pixel of an image has 3 values(RGB).
After getting the texture, I have no idea what I should do and where should I do them in initializeGL() or paintGL(). Can anyone tell the steps?
void MyOpenGLWidget::loadTexture(const char* file_path)
{
*image = cv::imread(file_path, cv::IMREAD_COLOR);
width = image->rows;
height = image->cols;
int channels = image->channels();
img_data = SOIL_load_image(file_path, &width, &height, &channels, SOIL_LOAD_RGB);
}

Why is unsigned char* img_data over unsigned char* img_data[3]
unsigned char* is a pointer to a buffer (of arbitrary length) of data. unsigned char* …[3] is an array of 3 pointers to buffers of data. You have only one buffer, not 3.
For some reason you're using both OpenCV and then SOIL to read the same image two times. Why?
Once you've loaded the image, to display it with OpenGL you have to
Create a texture object (glGenTextures, glBindTexture, glTexImage)
Create some geometry to draw it (usually a quad, or a viewport filling triangle), by filling a vertex buffer object (glGenBuffers, glBindBuffer, glBufferData) and associating the data in the buffer with vertex attributes of a vertex array object (glGenVertexArrays, glBindVertexArray, glEnableVertexArrayAttrib, glVertexAttribPointer)
Create a shader program, consisting of a vertex shader that places the geometry and paramtizes the fragment shader, which actually samples from the texture. (glCreateShader, glShaderSource, glCreateProgram, glLinkProgram)
Then to draw
select the shader program (glUseProgram)
set parameters (glUniform)
draw (glDrawArrays)

Related

Is there a way to batch render textures in Qt?

I have been trying to batch render two different pictures. I have 2 different QOpenGLTexture objects I want to draw in a single draw call with batch rendering but am struggling. Both texture objects have id's but only the last texture objects image is drawn. I believe my problem is with setting up the or frag shader.
//..............Setting up uniform...............//
const GLuint vals[] = {m_texture1->textureId(), m_texture2->textureId()};
m_program->setUniformValueArray("u_TextureID", vals, 2);
//..............frag Shader.....................//
#version 330 core
out vec4 color;
in vec2 v_textCoord; // Texture coordinate
in float v_index; // (0, 1) Vertex for which image to draw.
// 0 would draw the image of the first texture object
uniform sampler2D u_Texture[2];
void main()
{
int index = int(v_index);
color = texture(u_Texture[index], v_textCoord);
};
I've tried experimenting with the index value in the frag shader but it only draws the last texture image or blacks out. I tried implementing it how you would with openGL but have had no luck.

QT QVideoFrame memcpy zero-copy alternative

I get raw video data from the V4L2 driver using VIDIOC_DQBUF and I want to render this frames in qt using QVideoFrame as described here: https://blog.katastros.com/a?ID=9f708708-c5b3-4cb3-bbce-400cc8b8000c
This code works well but has huge performance issues.
Here is the problematik code part when doing this:
QVideoFrame f(size, QSize(width, height), width, QVideoFrame::Format_YUV420P);
if (f.map(QAbstractVideoBuffer::WriteOnly)) {
memcpy(f.bits(), data, size);
f.setStartTime(0);
f.unmap();
emit newFrameAvailable(f);
}
The memcpy operation for my 4K video reduces the framerate from 35fps to 5fps on my arm based embedded system.
This constructor is supposed to constructs a video frame from a buffer with the given pixel format and size in pixels. However I cannot find any example of this:
QVideoFrame::QVideoFrame(QAbstractVideoBuffer *buffer, const QSize &size, QVideoFrame::PixelFormat format)
I just need to pass valid buffer to QVideoFrame. I don't need to map or unmap the QVideoFrame. Like this:
unsigned char * pBuffer = get_pointer_to_a_frame();
QVideoFrame frame((QAbstractVideoBuffer *) pBuffer, QSize(width, height), QVideoFrame::Format_YUV420P);
frame.setStartTime(0);
emit newFrameAvailable(frame);
Any zero-copy QVideoFrame usage will wellcome.

How to create gray scale QImage(QImage::Format_Indexed) without copying memory

I'm trying to create QImage that wrap a existing image buffer that is created by OpenCv
I was considering use following constructor to do this.
QImage::QImage ( const uchar * data, int width, int height,
int bytesPerLine, Format format )
so, my code is like
QImage qimage((const uchar*)iplImage->imageData,
iplImage->width, iplImage->height,
iplImage->widthStep,
QImage::Format_Indexed); // image buffer not copied!
qimage.setColorTable(grayScaleColorTable); // color table's item count 256 for grayscale.
// now new image buffer is allocated here.
Ok, no memory copy actually was done at the time of calling this ctor.
But, here comes my problem. QImage::setColorTable() is non const member function where QImage allocates new image buffer for copying by its internal detach() function.
I found there was Qt3 support for this kind of problem where ctor could accept color table as argument in its ctor, but I've not found any such support in > Qt4.
How can I create gray scale QImage for existing image buffer?
Thanks for in advance
[EDITED]
Thanks to Stephen Chu, I realized that following contstructors create read/write-able QImage object
QImage ( uchar * data, int width, int height, Format format )
QImage ( uchar * data, int width, int height, int bytesPerLine, Format format )
which even if QImage::setColorTable() is called later right after instantiation, no new buffer is allocated. On the other hand, following constructors receiving 'const'ed data buffer create read-only QImage objects which new buffer is allocated and deep copied from original buffer when any non-const member function like QImage::setColorTable() is called(that I do not want).
QImage ( const uchar * data, int width, int height, Format format )
QImage ( const uchar * data, int width, int height, int bytesPerLine, Format format )

Is it possible to draw image using QGraphicsView from a 2D BYTE array Qt?

I have a 2D BYTE (unsigned char) array. buf[50][100] which is having some data. I need to draw this buffer to an image in Qt using QGraphicsView. The byte in (x,y) represents the (x,y)th pixel of the array. How to pass this array to the QGraphicsView to draw very fast? Or is there any other method (without using QGraphicsView) to draw the image in 2D array Please help.
You can create a QImage object from a pre-existing memory area and then you can use a drawImage call to draw it on a normal QPainter.
Being your image 8 bit per pixel you will need to also set up a palette for the image.
The palette is simply a mapping from a byte index to a QRgb color value. You can set it up like so:
static void setGrayColorMap(QImage * img)
{
img->setColorCount(256);
for (int i = 0; i < 256; ++i) {
img->setColor(i, qRgb(i,i,i));
}
}

Very big QImage and Memory Mapped Files in QT

I want bind QImage to the MMF file to manipulate the image without the cost of memory directly on the disc. Unfortunately, my code creates a copy in memory.
QFile file("Boston City Flow.jpg");
if(!file.open(QIODevice::ReadOnly))
QMessageBox::information(this, "Error", "Error");
qint64 size = file.size();
unsigned char *mmf = file.map(0, size);
QImage image;
image.loadFromData(mmf, size, NULL);
My program needs to handle very large images.
Try with declaring mmf const:
const unsigned char* mmf = file.map(0, size);
and then have a look at the QImage ctors, especially
QImage( const uchar*, int width, int height, Format )
QImage::QImage ( const uchar * data, int width, int height, Format format )
The docs say:
"The buffer must remain valid throughout the life of the QImage and all copies that have not been modified or otherwise detached from the original buffer. The image does not delete the buffer at destruction.
[...]
Unlike the similar QImage constructor that takes a non-const data buffer, this version will never alter the contents of the buffer. For example, calling QImage::bits() will return a deep copy of the image, rather than the buffer passed to the constructor. This allows for the efficiency of constructing a QImage from raw data, without the possibility of the raw data being changed."
Note that the non-const uchar* version copies the right away, so make sure to pass a const uchar*. Also note that calling non-const methods of QImage will copy the data.

Resources