Canvas image not grabbed in QQuickWindow - qt

I need to capture an image from QML which has Canvas elements. Whereas Canvases are displayed fine they are not correctly saved in the picture snapshots.
I have used QQuickWindow grabWindow method as described in the solutions of this link and the images are saved in the UI thread called by afterRendering signal (I have tried frameSwapped signal too). Result is that all QML objects are saved but not Canvas objects.
Both the renderStrategy and renderTargetof Canvases are set to the default values. They are simple Canvases as shown below:
Canvas {
id:canvas
onPaint:{
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(20, 0);
ctx.bezierCurveTo(-10, 90, 210, 90, 180, 0);
ctx.stroke();
//...
}
}
I have noticed that the afterRendering signal is called multiple times.
Any suggestion is really appreciated! :)

Related

Equivalent of BufferedImage (java awt) on JavaFx

I'm working with JavaFx and i'm looking for an equivalent of the AWT BufferedImage. I saw that I can used SwingFXUtils to used an awt BufferedImage with JavaFx but I don't want to used awt.
In fact I'm looking for a structure to display a table of pixel witch is associated to a ColorModel.
Does anybody know some equivalent with JavaFx ?
Thanks a lot.
The closest you get to a BufferedImage in JavaFX is javafx.scene.image.WritableImage. It is a subclass of javafx.scene.image.Image, and was introduced in JavaFX 2.2.
Depending on your use case, javafx.scene.canvas.Canvas and javafx.scene.canvas.GraphicsContext (similar to a Graphics2D Java2D) might be a better fit.
To paint on a Canvas node and get the contents in a WritableImage, use (adapted from the Canvas JavaDoc):
// Create canvas
Canvas canvas = new Canvas(250, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
// Paint on it
gc.setFill(Color.BLUE);
gc.fillRect(75, 75, 100, 100);
// NOTE: The canvas must be part of a Scene for the following to work properly, omitted for brevity
// Obtain a snapshot of the canvas
WritableImage image = canvas.snapshot(null, null);
See Working with Canvas from he JavaFX tutorials for more information.

Displaying live camera image in Qt GUI

Im trying to make an application that takes live image recorded by camera and shows it on screen using Qt GUI. The camera driver and api provides me with functionality that refreshes the memory block showed by pointer.
The problem is my image won't refresh inside Qlabel made with Qimage (code below)
QImage myImage(raw_image_data_pointer, 768, 576, QImage::Format_RGB32 );
QLabel myLabel;
myLabel.setPixmap(QPixmap::fromImage(myImage));
myLabel.show();
How can i get my QLabel to be refreshed?
The problem is that you create the label widget with a static image inside. The containing image is not "connected" to your camera anymore, but is just a copy of a frame of your video stream. In order to make QLabel to update itself, you have to constantly replace the containing image with new one. For example, you can set up a timer for that:
MyClass:MyClass()
{
QTimer *timer = new QTimer;
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(10); // Defines how often update the label.
myLabel = new QLabel;
[..]
}
// Slot
MyClass::update()
{
QImage myImage(raw_image_data_pointer, 768, 576, QImage::Format_RGB32 );
myLabel.setPixmap(QPixmap::fromImage(myImage));
}

Qt QLabel fails to resize

I implemented QLabel much like Qt's ImageViewer example, except I use QGridLayout for positioning my widgets. I also implemented similar lines for scaling my QLabel using QScrollBar, but QLabel just doesn't scale like it should inside the QScrollArea. I am not sure if it is related to some kind of GridLayout management issue or something else. I have been reading everywhere and trying different things for 3 days now. Below I list the relevant portion of my code.
In my Viewer class constructor:
{
imageLabel1 = new QLabel;
imageLabel1->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
imageLabel1->setScaledContents(true);
scrollArea1 = new QScrollArea;
scrollArea1->setWidget(imageLabel1);
scrollArea1->setWidgetResizable(true);
....
QGridLayout *centralLayout = new QGridLayout;
centralLayout->addWidget(scrollArea1, 0, 0);
...}
and my scaleImage method:
void Viewer::scaleImage1(int factor)
{
Q_ASSERT(imageLabel1->pixmap());
scaleFactor *= (1 + factor);
//imageLabel1->resize(scaleFactor* imageLabel1->pixmap()->size());
imageLabel1->pixmap()->toImage().scaled(scaleFactor* imageLabel1->pixmap()->size(), Qt::KeepAspectRatio, Qt::FastTransformation);
imageLabel1->adjustSize();
adjustScrollBar(scrollArea1->horizontalScrollBar(), factor);
adjustScrollBar(scrollArea1->verticalScrollBar(), factor);
imageLabel1->update();
}
My scaleImage1 function is a public slot, and it receives signal from a scrollbar that goes between 0 and 2 so that, into the scaleFactor, the imageLabel1 is designed to be capable of being zoomed in up to 3 times its original size. But when I run the code, I don’t observe the imageLabel becoming enlarged inside the QScrollArea, which I saw in the imageViewer demo. The imageLabel1 simply retains the original size as it is loaded and does not respond to the valueChange() of scrollbar.
I'd appreciate your advice/tips very much.
I think is because you set QSizePolicy::Minimum to the imageLabel, try with MinimumExpanding or other that better fit your needs.

add uicomponent inside a sprite

i want to add UIComponent inside a spite. here is the code:
private function make() : void {
var circle : Sprite = new Sprite();
circle.graphics.beginFill(0xFF0000, 0.2);
circle.graphics.drawCircle(0, 0, 20);
var button : Button = new Button();
button.label = "testing...";
var wrapper : UIComponent = new UIComponent();
circle.addChild( button );
wrapper.addChild( circle );
addChild( wrapper );
}
the problem is that button is added, but is not displayed. if i do reversed - add sprite to uicomponent - everything works fine, but this way it doesn't work. i tried to use invalidate functions for button etc... even tried making "circle" as UIMovieClip, but no luck - button is still invisible. also if i simply do "addChild( button );" - it is shown, what the... please help, what i am doing wrong? how can i add a button inside a sprite?
Short answer, you can't. What you CAN do is instead of using Sprite, you use UIComponent for your circle.
The reason for this is that UIComponent has A LOT of code that changes how it behaves, including how to add and layout children. You could essentially take the same code to a Sprite since UIComponent does extend it, however that would be VERY redundant. This works great for me:
private function make() : void {
var circle : UIComponent= new UIComponent();
circle.graphics.beginFill(0xFF0000, 0.2);
circle.graphics.drawCircle(0, 0, 20);
var button : Button = new Button();
button.label = "testing...";
var wrapper : UIComponent = new UIComponent();
circle.addChild( button );
wrapper.addChild( circle );
addChild( wrapper );
}
Unfortunately, in order to use Sprite the way you are trying to do it, you would have to extend Sprite and implement IUIComponent.
Taken from the Flex 3 Language Reference:
Note: While the child argument to the
method is specified as of type
DisplayObject, the argument must
implement the IUIComponent interface
to be added as a child of a container.
All Flex components implement this
interface.
Sprite does not implement IUIComponent, so you are experiencing a pretty typical issue. UIComponent's don't typically have speed issues when compared to Sprites, so I would recommend just drawing on your UIComponent.
As stated before, you /could/ extend Sprite to implement IUIComponent, but it's a pain.
Hope this helps!

How to add an image on the top of another image?

I want to show difference between a trimed clip and non trimed clip in my video editor application, i.e. I want to add a small film image on my thumbnail for a trimed clip. How can I do this?
It would be just to show the difference between an image and a video in our gallery application.
How to add an image on the top of another one in Qt?
Open the QPainter on the bottom image and draw the top image using its drawPixmap()/drawImage() methods.
QPixmap base, overlay; // come from your code
{
QPainter painter(base);
painter.drawPixmap(100, 100, overlay);
}
If your overlay contains an alpha channel (e.g. fancy PNG icon) and your base image does not, you should create a new QPixmap with an alpha channel and draw both images into it:
QPixmap base, overlay; // come from your code
QPixmap result(base.width(), base.height());
result.fill(Qt::transparent); // force alpha channel
{
QPainter painter(&result);
painter.drawPixmap(0, 0, base);
painter.drawPixmap(100, 100, overlay);
}
QPixmaps and QImages can be used interchangeably, although not all combinations give good performance).
If it's just about showing an image above another, then you could also go with this answer.
QGridLayout *layout = new QGridLayout(widget);
Pixmap base, overlay;
QLabel *background = new Label();
background->setPixmap(&base);
QLabel *lOverlay = new QLabel();
lOverlay->setPixmap(&overlay);
//label gets positioned above textBrowser and is an overlay
layout->addWidget(background, 0, 0, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(lOverlay, 0, 0, Qt::AlignRight | Qt::AlignBottom);
Of course then the QPixbuf of the background doesn't contain the QPixbuf of the overlay-image, but it only appears to do.

Resources