How to pass the image preview from the QML Camera component to a C++ plugin

6,163

Solution 1

You can get valid engine instance using following syntax.

QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();

And to get pointer of image provider, you can do something like following,

QQmlImageProviderBase* imageProviderBase = engine->imageProvider(item.host());
QQuickImageProvider* imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase);

As QQuickImageProvider is derived from QQmlImageProviderBase, I think this cast is ok. Not sure how otherwise we can get pointer of QQuickImageProvider from engine.

Solution 2

To get the preview image in C++, you should pass the mediaObject property of the QML Camera element to C++. You can see that code in the camera-app as example.

You could try to use the QCameraImageCapture with that mediaObject. But I'm not sure if that will work. But it has the imageCaptured signal you'll need. That has a QImage with the preview.

void AdvancedCamera::setCamera(QObject *cameraObject)
{
    QVariant cameraVariant = cameraObject->property("mediaObject");
    QCamera *camera = qvariant_cast<QCamera*>(cameraVariant);
    QCameraImageCapture *imageCapture = new QCameraImageCapture(camera);
    QObject::connect(imageCapture, SIGNAL(imageCaptured(int, const QImage&))
        myObject, SLOT(processPreview(int, const QImage&)));
}

If it doesn't work, here is another way, using the QCameraImageCaptureControl of the QMediaService:

void AdvancedCamera::setCamera(QObject *cameraObject)
{
    QVariant cameraVariant = cameraObject->property("mediaObject");
    QCamera *camera = qvariant_cast<QCamera*>(cameraVariant);
    QMediaService *service = camera->service();
    QMediaControl *control = service->requestControl(QCameraImageCaptureControl_iid);
    QCameraImageCaptureControl *captureControl = qobject_cast<QCameraImageCaptureControl*>(control);
    QObject::connect(captureControl, SIGNAL(imageCaptured(int, const QImage&))
        myObject, SLOT(processPreview(int, const QImage&)));
}

You should look a the code of the camera-app for a better example.

For getting the final image delivered as QVideoFrame in C++, you would need to set the captureDestination. But that's not (yet?) supported by the camera backend of the Ubuntu phones.

Share:
6,163

Related videos on Youtube

David Planella
Author by

David Planella

I work at GitLab as Director of Community Relations. Before, I worked for Canonical as the former Ubuntu Community Team Manager. As an Open Source contributor, I am mostly involved in app development and localization: I'm the developer of Qreator, former lead the Ubuntu Catalan Translators team and also a GNOME translator. In the past I've contributed to other projects, such as Debian or Mozilla. Blog Google+ Twitter

Updated on September 18, 2022

Comments

  • David Planella
    David Planella over 1 year

    I'm writing an Ubuntu Touch QML app that captures and processes images from a camera device. The processing is done by a C++ plugin to which I'm passing the URL of the image.

    I can successfully save images and load them from the C++ plugin, but I'd rather not have to save the images on the filesystem first, and pass the in-memory camera preview to the plugin instead.

    Given the URL for the preview that I'm getting from the camera (image://camera/preview_1), I'm guessing I should be able to get a reference to the "camera" image provider and then use the requestImage() method to get the image.

    However, I've not been able to figure out how to get hold of the camera image provider. Here's the code:

    QString Decoder::decodeImageQML(const QUrl &imgUrl)
    {
        /* 
         * @imgUrl: URL to the camera preview. E.g. image://camera/preview_1
         */
    
        QQmlEngine * engine;
        QQuickImageProvider *imageProvider = 0;
    
        // FIXME: this does not work, I'm not sure how to get hold of 
        // the image provider
        imageProvider = engine->imageProvider("camera");
    
        QImage image = imageProvider->requestImage(("preview_1", &size, QSize());
    
        return Decoder::decodeImage(image);
    }
    

    How do I get a reference to the camera image provider?

    • Kunal
      Kunal almost 11 years
      I had done similar thing in one of my app, but I chosen opposite approach. I was getting preview image using View Finder and processing in c++ plugin and then sharing them to QML app using custom Image provider.
  • ssc
    ssc almost 11 years
    I think you should use a dynamic_cast instead of a static_cast and possibly check the result, see e.g. stackoverflow.com/questions/28002/…