I have a requirement to read pixel values from the picture displayed on the GraphicScene layout. How can I display image using QImage without using pixmap in Qt so that I am able to read the pixel values?
On most platforms, a QPixmap is a thin wrapper around a QImage. The conversions between the two are cheap - especially the pixmap-to-image conversion. Thus, you can use the QGraphicsPixmapItem and use item->pixmap().toImage() without much worry. To confirm that QPixmap is indeed a wrapper, the following check will do:
bool isPixmapThin(const QPixmap &pix) {
auto const a = pix.toImage();
auto const b = pix.toImage();
return a.bits() == b.bits();
}
In all cases, ensure that the image you take from the pixmap won't detach, i.e. always make it const (as in the code example above).
Related
I will get raw video data from the V4L2 driver using VIDIOC_DQBUF, I wanted to render this frame in qt using QVideoFrame(which construct video frame) and QLabel/QPaint(for rendering a video frame).
QVideoFrame::QVideoFrame(QAbstractVideoBuffer *buffer, const QSize &size, QVideoFrame::PixelFormat format)
Constructs a video frame from a buffer with the given pixel format and size in pixels.
Qvideoframe from Qt
As of now, I’m using QImage to rendering RGB24 and QImage supports the only RGB format. However raw video frame which is received from VIDIOC_DQBUF is having different color formats and QVideoFrame support most of them.
Queries:
How to use QVideoFrame::QVideoFrame(QAbstractVideoBuffer *buffer, const QSize &size, QVideoFrame::PixelFormat format) for v4l2 buffer ?
How I can use map(), bits() and mappedBytes() function so that, I can get QVideoFrame constructed for given raw video data?
How I can use QPaint/QLabel to render QVideoFrame?
Regards,
Kulakrni
Lets reverse the order.
How I can use QPaint/QLabel to render QVideoFrame?
You can not. You need to use a QAbstractVideoSurface() derived class. In QML, this is VideoOutput. If you want a single image, then QVideoFrame is not the correct class to use for QPaint/QLabel.
How I can use map(), bits() and mappedBytes() function so that, I can get QVideoFrame constructed for given raw video data?
These functions are your interface to the QAbstractVideoSurface. It depends on how you want to store the VL4 buffer. Are you copying/translating it or are you mapping it directly; then there are ownership issues which this API attempts to address.
How to use QVideoFrame::QVideoFrame(QAbstractVideoBuffer *buffer, const QSize &size, QVideoFrame::PixelFormat format) for v4l2 buffer
You need to sub-class a QAbstractVideoBuffer by either copying/translating the data and keeping it with the class or provide a reference if you are using zero-copy of some sort.
By default, QML Camera and QCamera will find and use /dev/videoX which is a v4l device, via GStreamer. This class should already do the right thing to supply a VideoOutput widget.
See: Qt Video overview
How to clear or clean up a QIMage
Following method of mine get a const reference to a QIMage.
MyMethod(const QImage & img) {
// save it to a file
img.save("/path/to/save/the/qimage");
// now I want to clan up img from memory. How should I do it?
}
Question:
How should I clean up the QImage object from memory after use?
Note:
Note that it is a const & QImage. So, answer would involve casting the QImage into non-const?
Also, I am looking at trying to get a QImageData pointer to the data & delete it. Not sure if that is the correct approach here. Do suggest.
You need a non-const reference or a pointer. With a pointer the answer is obvious. With a reference you just assign a default-constructed QImage to it.
MyMethod(QImage & img) {
img.save("/path/to/save/the/qimage");
img = QImage();
}
However, this may still not clean up the memory occupied by the image, if there are additional QImage instances referencing that same image. To overcome this hurdle you need to avoid multiple QImage instances referencing the same image. A Qimage instance is like a shared pointer in this regard.
A const-cast would be considered to reveal a design flaw in your case. I'd recommend against it.
I have been playing with QMovie a bit trying to mirror a movie as well as play it in reverse.
For the mirroring bit I tried assigning a negative width to no avail. Since QImage does offer facilities for this I had hoped QMovie would do the same.
There don't seem to be any facilities in the QMovie object for those things, so I'm wondering if I could manipulate the QIODevice to the QMovie object instead to achieve this, but this is completely new territory for me and I don't see anything obvious in the documentation that would achieve mirroring or playing in reverse.
The code example to start with would be the same as on the PySide page:
label = QLabel()
movie = QMovie("animations/fire.gif")
label.setMovie(movie)
movie.start()
Any ideas would be greatly appreciated.
Thanks,
Frank
QMovie doesn't provide the methods to set the current image, so you have to use directly QImageReader to play it in reverse (using QImageReader::jumpToImage()). This is not very easy bacause the delay between a frame and the next can change, but however you can get it calling QImageReader::nextImageDelay().
To display the movie, you can implement your own widget to draw the movie as you want.
In the paintEvent() you can set a transformation to the painter to get the mirror effect and than draw the current image of the movie.
Example:
void MyWidget::paintEvent(QPaintEvent * event)
{
QPainter painter(this);
painter.scale(-1, 1); // x-axis mirror
//here maybe you must adjust the transformation to center and scale the movie.
painter.drawImage(0, 0, currentImage);
}
To play the movie you have to set a timer that change the current image.
Example:
//you must create a timer in the constructor and connect it to this slot
void MyWidget::timeoutSlot()
{
int currentImageIndex;
//here you have to compute the image index
imageReader.jumpToImage(currentImageIndex);
currentImage = imageReader.read(); //maybe you want to read it only if the index is changed
update();
}
Here you can find an example of widget subclass, with timer and painter transformation
See also QImageReader, QTimer, QWidget::paintEvent
I am creating QGraphicsPixmapItems by loading images from files.
bool PixMapItem::loadItemFromFile(const QString &filename)
{
QPixmap p;
if(!p.load(filename))
return false;
setPixmap(p);
#ifdef NOT_QT_4
m_itemSize = p.size()/p.devicePixelRatio();
#else
m_itemSize = p.size();
#endif
return true;
}
caller:
item->loadItemFromFile(filename);
item->adjustForMaxSize(maxSize);
I would like to know how the memory used by the item depends on the image file size.
1) Type of image - will the encoding of the Pixmap stored in the item be minimal, or always 32 bit, or is there any way to set it ?
2) Assuming the item is resized immediately after load to match a specific size (see above), would the actual image size affect the item memory size ? Would memory size be better if I scale the pixmap instead of the item itself ?
Let me try to answer it, maybe it help you :
I have try long time ago and yes it will always 32 bit, it will be RGB or RGBA (if there is alpha on image, it can be check by hasAlpha). The way you can check is check the depth of the QPixmap which always return 32. Nothing we can do with the pixmap data because it handle internally, which stated on their QPixmap documentation :
Note that the pixel data in a pixmap is internal and is managed by the
underlying window system.
Smaller image will be smaller memory consumed. And you need to free your original pixmap after scale it.
QPixmap is design for painting performance on screen, if you want better handle IO (formating image, decrease the color, etc) use QImage. You also able to render QImage to screen using the painter but it will be slower compare to QPixmap.
I'd like to display some QImage through QGraphicsScene, my code's very straightforward:
mainwindow.h
QImage *sourceImage;
QGraphicsView *imageView;
QGraphicsScene *imageScene;
mainwindow.cpp
imageScene = new QGraphicsScene;
imageView = new QGraphicsView;
imageView->setScene(imageScene);
sourceImage = new QImage;
sourceImage.load(":/targetimage.png");
imageScene.addPixmap(QPixmap::fromImage(sourceImage));
And then the complier points out exactly what I did wrong: QGraphicsScene::addPixmap accepts only const QPixmap as argument, and I was trying to convert QImage to const QPixmap, which is not allowed because QPixmap::fromImage within only accept const QImage, like a const hell.
The official documentation on this method doesn't make much sense to me either, if I'd like to make for example, an image viewer, and during runtime I'd sure load different images into QImage sourceImage, and how can I accomplish that using a const QImage?
This problem has been agonizing, thanks for any advice. Moreover could you light me a bit if there's any vision on the philosophical reason why guys in Qt make these methods const?
Try
imageScene.addPixmap(QPixmap::fromImage(*sourceImage));
Some advice:
there is no need to allocate the QImage on the heap (using new).
Use:
QImage sourceImage;
Then you do not need to dereference the pointer when calling QPixmap::fromImage
Just to clarify: the constness has nothing to do with the error.