How load QImage from path? - c++

I captured an Image with camera in my qt quick application.I want to send the path to my c++ code and load that Image in c++ QImage.But the Path is image://camera/preview_1 and I don't know How work with that path?
Camera {
id: camera
imageCapture {
onImageCaptured: {
console.log("Preview = "+preview);
photoPreview.source = preview
console.log("CapturedImagePath => "+camera.imageCapture.capturedImagePath);
up.loadImage(preview);
}
}
c++ class
void UserProfile::loadImage(QString path)
{
QUrl imageUrl(path);
qWarning()<<"imageUrl.host()=>"<<imageUrl.host();
qWarning()<<"imageUrl.path()=>"<<imageUrl.path();
qWarning()<<"imageUrl.toLocalFile()=>"<<imageUrl.toLocalFile();
bool isOpend= m_image.load(path); //m_image is an QImage object
qWarning()<<"Image loaded=> "<<isOpend;
}
Application output
D MyApp: qml: Preview = image://camera/preview_1
D MyApp: qml: CapturedImagePath =>
W MyApp: imageUrl.host()=> "camera"
W MyApp: imageUrl.path()=> "/preview_1"
W MyApp: imageUrl.toLocalFile()=> ""
W MyApp: Image loaded=> false

The URL image://camera/preview_1 means that the image data is living in a QQuickImageProvider instance. Probably, it's a QQuickImageProvider instance created by Camera.
As the UserProfile instance is living in the same QQmlEngine as the camera lives, you can
void UserProfile::loadImage(const QString &path)
{
auto myQmlEngine = qmlEngine(this);
if(myQmlEngine==nullptr)
return;
QUrl imageUrl(path);
auto provider = reinterpret_cast<QQuickImageProvider*>( myQmlEngine->imageProvider(imageUrl.host()));
if (provider->imageType()==QQuickImageProvider::Image){
QImage img = provider->requestImage(imageUrl.path().remove(0,1),nullptr,QSize());
// do whatever you want with the image
}
}
Be careful with the reinterpret_cast. You also have to make sure that the QQuickImageProvider::imageType() is returning QQmlImageProviderBase::Image.
and you could also use capturedImagePath instead of the preview URL to prevent this complexity if it could be an option for your usecase.

Related

How to flip image from QCamera?

In QT Creator how we can filp the images from camera. I googled a lot but I didn't get a proper solution.
Following is my code.
mCamera = new QCamera;
mViewfinder = new QCameraViewfinder;
mLayout = new QVBoxLayout(ui->graphicsView);
mLayout->addWidget(mViewfinder);
mCamera->setViewfinder(mViewfinder);
mViewfinder->show();
mCamera->start();
I tried QCamera::FrontFace and QCamera::BackFace in constructor argument in QCamera like below
mCamera = new QCamera(QCamera::FrontFace);
and
mCamera = new QCamera(QCamera::BackFace );
But both have no difference.
In Python
video=cv2.flip(self.frame,1)
will solve the problem,
Any idea how to solve this ..
I am using Windows 10
QCamera::FrontFace and QCamera::BackFace are just positions of the camera. To achieve what you want, you should flip every image.
Create QCameraImageCapture and connect to its imageCaptured() signal.
auto imageCapture = new QCameraImageCapture( mCamera );
connect(imageCapture, &QCameraImageCapture::imageCaptured, [&](int id, const QImage &preview){
QImage flipped = preview.mirrored();
// do what you want with flipped image
})
Documentation says that mirrored(bool horizontal = false, bool vertical = true)
Returns a mirror of the image, mirrored in the horizontal and/or the vertical direction depending on whether horizontal and vertical are set to true or false.
UPDATE:
I found the camera and tested the code and realized that I forgot one important thing. You need to use a timer by which QCameraImageCapture will capture the image.
Create QTimer and connect to QTimer::timeout() signal:
connect (&timer, &QTimer::timeout, [&](){
camera->searchAndLock();
imageCapture->capture();
camera->unlock();
});
And after that start the timer. To show flipped image you can use just QLabel class with label->setPixmap(QPixmap::fromImage(flipped)) method.
Hai I changed my code as per the answer of #Allocse and its work for me
My full code will be
mCamera = new QCamera;
mCamera->start();
imageCapture = new QCameraImageCapture( mCamera );
connect (&timer, &QTimer::timeout, [&](){
mCamera->searchAndLock();
imageCapture->capture();
mCamera->unlock();
});
connect(imageCapture, &QCameraImageCapture::imageCaptured, [&](int id, const QImage &preview){
QImage flipped = preview.mirrored(true,false);
ui->videoFrame->setPixmap(QPixmap::fromImage(flipped));
});
timer.start();
Note :-mCamera and imageCapture should be declared in class decleration

Image Streaming using QGraphicsView

I am trying to display images from a CameraLink Camera into a QGraphicsView.
I am using a ring buffer which get() and set() functions and two threads that consume or produce the images in this ring buffer.
This part works because I already had a successfull streaming using a QWidget. I want to use a QGraphicsView because I want to draw over those incoming images
I have a display class which is promoted to QGraphicsView, everytime an image is produced, a signal is emitted from the consumer thread to the following function:
void display::drawImage(ImageBW* image)
{
firstImage = image;
QRect rect;
rect.setHeight(1000);
rect.setWidth(2000);
QApplication::postEvent(this->viewport(),new QPaintEvent(rect));
}
I have reimplemented the painEvent of the QGraphicsview class:
void display::paintEvent(QPaintEvent *event)
{
if(firstImage)
_drawImage();
event->setAccepted(true);
}
and the drawing function is:
void display::_drawImage()
{
int w, h;
if(img)
{
delete img;
img = NULL;
}
w = firstImage->getSizeX();
h = firstImage->getSizeY();
unsigned char * udata = (unsigned char *)firstImage ->getData();
img = new QImage(udata,w, h,QImage::Format_Grayscale8);
pix_img = QPixmap::fromImage(*img);
scene->clear();
scene->addPixmap(pix_img);
scene->setSceneRect(pix_img.rect());
scene->update();
update(); // I have tried here also setScene(scene)
}
In the above code, firstImage is an ImageBW* variable. ImageBW is where the image data from camera is stored.
I have also tried with QGraphicsItem and addItem() function but i get no Image.
'scene' is initialized on the producer of this class and also the 'setScene(scene);' command is there.
The program stucks after a while so that probably means that this code produces stackoverflow.
Please I have tried everything i can think of, any help would be greatly appreciated.
Thanks in advance

Save QML image inside c++

I am trying to display network image using qml and then save this image using c++ code,
Here is the qml code,
import QtQuick 2.3
import QtQuick.Window 2.2
import com.login 1.0
Window {
visible: true
width : 500
height: 500
Login{id: login}
MouseArea {
anchors.fill: parent
onClicked: {
// Qt.quit();
login.save(image);
}
}
Image {
id: image
source: "http://www.test.com/webp/gallery/4.jpg"
}
}
And inside my login class saving image like,
void Login::save( QQuickItem *item)
{
qDebug()<<"width: "<<item->width();
qDebug()<<"height: "<<item->height();
QQuickWindow *window = item->window();
QImage image = window->grabWindow();
QPixmap pix = QPixmap::fromImage(image);
pix.save("C:/Users/haris/Desktop/output.png");
}
I am getting the correct width and height of the image inside c++ class, but the problem is I cannot find a way to save the image item from QQuickItem.
Right now I am saving the image by grabing the window, which actually not giving the actual image size on output file, instead giving output file with current qml window size.
Basically I am following the code here saving QML image but it seems QDeclarativeItem is deprecated in Qt5, so I choose QQuickItem where as there is no paint option in QQuickItem.
Fortunately QQuickItem has a convenient grabToImage function which does that.
void Login::save( QQuickItem *item)
{
QSharedPointer<const QQuickItemGrabResult> grabResult = item->grabToImage();
connect(grabResult.data(), &QQuickItemGrabResult::ready, [=]() {
grabResult->saveToFile("C:/Users/haris/Desktop/output.png");
//grabResult->image() gives the QImage associated if you want to use it directly in the program
});
}
Alternate solution without using lambdas:
void Login::save( QQuickItem *item)
{
QSharedPointer<const QQuickItemGrabResult> grabResult = item->grabToImage();
/* Need to store grabResult somewhere persistent to avoid the SharedPointer mechanism from deleting it */
...
connect(grabResult.data(), SIGNAL(ready()), this, SLOT(onAsynchroneousImageLoaded()));
}
void Login::onAsynchroneousImageLoaded() {
auto grabResult = qobject_cast<const QQuickItemGrabResult*>(sender());
if (grabResult) {
grabResult->saveToFile("C:/Users/haris/Desktop/output.png");
} else {
//something went wrong
}
});
In a QObject-derived class (ImageSaver) register it as you would. It needs one member:
bool ImageSaver::saveImage(const QUrl &imageProviderUrl, const QString &filename){
qDebug() << Q_FUNC_INFO <<imageProviderUrl << filename;
QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
QQmlImageProviderBase *imageProviderBase = engine->imageProvider(imageProviderUrl.host());
QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase);
QSize imageActualSize;
QSize imageRequestedSize;
QString imageId = imageProviderUrl.path().remove(0,1);
QImage image = imageProvider->requestImage(imageId, &imageActualSize, imageRequestedSize);
qDebug() << Q_FUNC_INFO << imageId << imageActualSize;
return image.save(filename);
}
then in QML:
ImageSaver { id: imageSaver}
...
imageSaver.saveImage(image.source, "my.png");
...
Whereas grabToImage will grab the item using the items's size, this can preserve the actual size of the image.

QWidget::grab function for videos: cannot catch

I want to save the current window to an image (like as ATL+PrintScreen) in Qt. Example, for the Qt Media Player Example (you can get all the code in Qt Creator examples when search "player", I added this code to player.h :
//private slots:
...
void exportVideoToImages();
and in player.cpp:
void Player::exportVideoToImages()
{
qDebug() << "ok";
QPixmap const& px = grab();
px.save("File.png");
}
Add this line to the the constructor to trigger the slot:
new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_G), this, SLOT(exportVideoToImages()));
So, when I trigger CTRL+G, I will receive an image "File.png". It worked, but the problem is the playing video cannot be catch.
This is the two images, one from Alt+PrintScreen and one from the program:
Why is it? How can I grab the video in Qt? Can you show me?
Thank you very much!
I found the solution:
QScreen *screen = QGuiApplication::primaryScreen();
if (screen) {
QPixmap px =screen->grabWindow(this->winId());
px.save("screen.png");
}

BlackBerry 10 - Adding ImageView to Container

I'm trying to add an ImageView to container, by it doesn't appear on the screen.
Container is created in QML, but I want image to be added in .CPP file.
ApplicationUI.cpp:
ApplicationUI::ApplicationUI(bb::cascades::Application *app)
: QObject(app)
{
QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
AbstractPane *root = qml->createRootObject<AbstractPane>();
ImageView* imageView1 = new ImageView();
imageView1->setImage(Image("asset:///icon.png"));
Page *page = qml->createRootObject<Page>();
Container *_mRootContainer = page->findChild<Container*>("rootContainer");
_mRootContainer->add( imageView1 );
app->setScene(root);
}
main.xml:
import bb.cascades 1.0
Page {
Container {
objectName: "rootContainer"
Label {
text: "First page"
}
}
}
Thanks in advance ;)
You can create an image container in your .CPP file and then create/add all your images to your container. Eg: using the DockLayout here for images ontop of each other and centered them within parent container.
//Create the images container and center it within parent container
Container *imageContainer = new Container();
imageContainer->setLayout(new DockLayout());
imageContainer->setHorizontalAlignment(HorizontalAlignment::Center);
//Create the image (add the image file into asset folder)
ImageView* imageView1 = ImageView::create("asset:///icon.png");
//Align/center image horizontally and vertically within parent container
imageView1->setHorizontalAlignment(HorizontalAlignment::Center);
imageView1->setVerticalAlignment(VerticalAlignment::Center);
//Add images to image container
imageContainer->add(imageView1);
I recommed to show the image in a WebView
Best of luck