What is the HDC for in GetDIBits? - gdi

I was using GetDIBits to get bitmap data from a screen compatible device context into a DIB of a certain format. I was under the impression that the DC was necessary only for synthesizing a color table when the source bitmap is 8 bits-per-pixel or less. Since my source bitmap was a full 32-bit color image and this was a one-off program and I didn't have the screen DC handy, I set the HDC parameter to NULL. This didn't work. Once I grabbed the screen DC and passed it in, it did start working.
That left me wondering why GetDIBits requires the device context. What is it used for?

In:
int SetDIBits(
__in HDC hdc,
__in HBITMAP hbmp,
__in UINT uStartScan,
__in UINT cScanLines,
__in const VOID *lpvBits,
__in const BITMAPINFO *lpbmi,
__in UINT fuColorUse
);
The second argument hbmp is the device dependent bitmap that will be altered using the color information from the device independent bitmap. The hdc is a handle to the device context on which this (device dependent) bitmap depends. When the call is made, Windows uses information from this device context to decide how to perform the transformation.

Related

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.

Qt - steps to using QOpenGLWidget to display images

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)

How do I pass a device memory buffer with offset to my kernel

I have allocated a buffer on the device:
cl_mem buff;
I want to pass this buffer plus an offset to my kernel
i.e.
buff + offset;
I find that this is not allowed. If I instead pass buff into my kernel and then
calculate the offset buffer inside the kernel, then this is fine. But it adds a needless calculation to each kernel run.
So, I get that the device memory space is different than the host, so I can't do simple pointer arithmetic. But, is there a way of taking an address to a device memory buffer,
calculating an offset, and passing this offset buffer into the kernel?
I think this may be possible with clCreateSubBuffer, but the offset needs to be aligned to the device's CL_DEVICE_MEM_BASE_ADDR_ALIGN, and this is not always possible for my kernel.
Using clCreateSubBuffer
If offset can be calculated statically, export macro, when building Program of your Kernel;
Assuming you are using C++
std::string macro;
std::stringstream ss;
// e. g. let it be 2^10
std::size_t offset = 1024;
ss << offset;
macro = "-D offset=";
macro += ss.str();
...
// When building Programm
clBuildProgram(..., macro.c_str(), ...);
//Inside your Kernel macro "offset" is defined
void __kenel my(
__global const uchar* data)
{
__global const uchar* data_with_shift = data + offset;
return;
}
Though, calculations inside kernel are extreamly cheap, so Marco13 gave you good advice.

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 )

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