2015-10-29 2 views
3

Я пытаюсь передать QImage в QML. Может кто-нибудь мне помочь? Код ниже.Pass QImage to QML

Проблема в том, что все мои попытки сделать изображение доступным для поставщика изображений терпят неудачу. Я попытался использовать Q_PROPERTY и член QImage внутри класса, но мой провайдер всегда возвращает нулевое изображение, когда я пытаюсь получить к нему доступ, чтобы вернуться.

Как я могу сделать QImage доступным для провайдера?

QML

Camera { 
    id: camera 

    captureMode: Camera.CaptureStillImage 

    imageCapture { 
     onImageCaptured: { 
      manipulaImagem.imagem = preview; 

      previewImage.source = manipulaImagem.recortarFotoPerfil(preview, viewfinder.mapRectToSource(Qt.rect(viewfinder.x, viewfinder.y, viewfinder.width, viewfinder.height))); 
     } 
    } 
} 
Image { 
    id: previewImage 

    fillMode: Image.PreserveAspectFit 
    anchors.top: parent.top 

    width: parent.width 
    height: parent.width 
} 

CPP

QImage manipulaImagem::recortarFotoPerfil(const QString &imagem, QRect rectRecorte) 
{ 
    QUrl caminhoImagem(imagem); 
    QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine(); 
    QQmlImageProviderBase *imageProviderBase = engine->imageProvider(caminhoImagem.host()); 
    QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase); 

    QSize imageSize; 
    QString imageId = caminhoImagem.path().remove(0, 1); 
    QImage imagem1 = imageProvider->requestImage(imageId, &imageSize, imageSize); 
    imagem1 = imageProvider->requestImage(imageId, &imageSize, imageSize); 
    return imagem1; 
} 

Когда я использую это я получаю следующее сообщение: Ошибка: Невозможно назначить QImage для QUrl

я не нашел ничего, чтобы помочь мне чтобы решить эту проблему. Как я могу это сделать?


Я попробовал другой подход, используя поставщика изображения, как это предлагается по ссылкам, но он по-прежнему не работает

Вот код

.h

#ifndef MANIPULAIMAGEM_H 
#define MANIPULAIMAGEM_H 

#include <QObject> 
#include <QImage> 
#include <QQuickImageProvider> 
#include <QQmlEngine> 
#include <QQmlContext> 

class manipulaImagem : public QObject, public QQuickImageProvider 
{ 
    Q_OBJECT 

public slots: 
    QString recortarFotoPerfil(const QString &imagem, QRect rectRecorte); 

public: 
    manipulaImagem(QObject *parent = 0); 

    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize); 

private: 
    void alocaImagem(const QString &imagem, QRect rectRecorte); 

    QImage imagemEditada; 
}; 

#endif // MANIPULAIMAGEM_H 

. cpp

#include "manipulaimagem.h" 

#include <QDebug> 

manipulaImagem::manipulaImagem(QObject *parent) : QQuickImageProvider(QQmlImageProviderBase::Image) 
{ 

} 

QImage manipulaImagem::requestImage(const QString &id, QSize *size, const QSize &requestedSize) 
{ 
    if(imagemEditada.isNull()) 
    { 
     qDebug() << "Request image: (image is null)"; 
    } 
    else 
    { 
     qDebug() << "Request image: image is OK"; 
    } 

    return imagemEditada; 
} 

void manipulaImagem::alocaImagem(const QString &imagem, QRect rectRecorte) 
{ 
    QUrl caminhoImagem(imagem); 
    QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine(); 
    QQmlImageProviderBase *imageProviderBase = engine->imageProvider(caminhoImagem.host()); 
    QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase); 

    QSize imageSize; 
    QString imageId = caminhoImagem.path().remove(0, 1); 
imagemEditada = imageProvider->requestImage(imageId, &imageSize, imageSize); 

    if(imagemEditada.isNull()) 
    { 
     qDebug() << "Loading image failed"; 
    } 
    else 
    { 
     qDebug() << "Loading image OK"; 
    } 
} 

QString manipulaImagem::recortarFotoPerfil(const QString &imagem, QRect rectRecorte) 
{ 
    this->alocaImagem(imagem, rectRecorte); 

    QString a = "image://ProvedorImagens/imagemEditada"; 

    if(imagemEditada.isNull()) 
    { 
     qDebug() << "Imagem is null"; 
    } 
    else 
    { 
     qDebug() << "Imagem is loaded"; 
    } 

    return a; 
} 

.qml

ManipulaImagem { 
    id: manipulaImagem 
} 

Camera { 
      id: camera 

      captureMode: Camera.CaptureStillImage 

      imageCapture { 
       onImageCaptured: { 
        previewImage.source = manipulaImagem.recortarFotoPerfil(preview, viewfinder.mapRectToSource(Qt.rect(viewfinder.x, viewfinder.y, viewfinder.width, viewfinder.height))); 
       } 
      } 
     } 

Rectangle { 
    id: previewRectangle 

    visible: false 

    anchors.fill: parent 

    Image { 
     id: previewImage 

     fillMode: Image.PreserveAspectFit 

     anchors.top: parent.top 

     width: parent.width 
     height: parent.width 
    } 

Выход этого кода:

  • Загрузка изображения OK

  • Imagem загружается

  • Запрос изображения (изображение является нулевым)

QML Изображение: Не удалось получить изображение от поставщика: изображение: // provedorimagens/imagemEditada

Что происходит, что, когда я звоню функции изображение не равно нулю, но когда я пытаюсь вернуть QImage с помощью поставщика его Не могу вернуть изображение. Я не знаю, почему, но для поставщика изображений изображение равно null.

Как я могу это решить?

+1

Вы должны реализовать собственный поставщик изображения для того, чтобы использовать 'QImage' в QML.У меня есть пример, заданный в этом ответе: http://stackoverflow.com/questions/27429371/qml-and-c-image-interoperability/27429586#27429586 просто измените его для 'QImage' вместо' QPixmap' – dtech

+1

Возможный дубликат из [Qt/QML: отправить QImage из C++ в QML и отобразить QImage On GUI] (http://stackoverflow.com/questions/20691414/qt-qml-send-qimage-from-c-to-qml-and- display-the-qimage-on-gui) – hyde

+0

Проблема в том, что все мои попытки сделать изображение доступным для поставщика изображений не удались. Я попытался использовать Q_PROPERTY и член QImage внутри класса, но мой провайдер всегда возвращает нулевое изображение, когда я пытаюсь получить к нему доступ, чтобы вернуться. – GuiDupas

ответ

6

Ответ на мой вопрос Проблема решена. Вот шаг за шагом решение:

1 - Создание class, который наследуется от QQuickImageProvider и QObject и внутри него создать Image элемент (QImage) это изображение, которое будет предусмотрено.

class provedorImagem : public QObject, public QQuickImageProvider 

Внедрение метода virtual requestImage. Это метод, который возвращает изображение в QML

QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) 

Создайте метод загрузки изображения провайдера вернуть

void provedorImagem::carregaImagem(QImage imagemRecebida) 
{ 
    imagem = imagemRecebida; 
} 

Теперь установить его в качестве поставщика двигателей изображения в файле main.cpp

provedorImagem *provedorImg = new provedorImagem; 
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg); 

2 - Создайте еще class, который наследует от QObject.

class processaImagem : public QObject 

Внутри этого класса необходимо реализовать метод, который получит изображение от camera поставщика, выполнять изменения изображений и возвращает измененное изображение. PS: p_caminhoImagem - это property, который я создал внутри processaImagem class, который принимает camera preview path.

QImage processaImagem::carregaImagem() 
{ 
    QUrl caminhoImagem(p_caminhoImagem); 
    QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine(); 
    QQmlImageProviderBase *imageProviderBase = engine->imageProvider(caminhoImagem.host()); 
    QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase); 


    QSize imageSize; 
    QString imageId = caminhoImagem.path().remove(0, 1); 
    QImage imagem = imageProvider->requestImage(imageId, &imageSize, imageSize); 

    if(imagem.isNull()) 
    { 
     imagem = QImage(); 
    } 
    else 
    { 
     //Perform the modifications 
    } 

    return imagem; 
} 

3 - Теперь основная часть. Метод поставщика requestImage должен получить измененное изображение из processaImagem class, чтобы предоставить его QML. Для того, чтобы сделать это поставщик class pointer должен быть доступен в файле QML, так, в файле main.cpp просто сделать указатель доступным для QML как property

engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg); 

и зарегистрировать processaImagem class как тип QML

qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem"); 

Теперь мы связываем его внутри QML файл

ProvedorImagem.carregaImagem(processaImagem.carregaImagem()); 

4 - Это сделано. Теперь просто запросить изображение от поставщика:

imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString(); 

Вот весь код:

main.cpp

#include <QGuiApplication> 
#include <QQmlApplicationEngine> 

#include <QtQml> 

#include "processaimagem.h" 
#include "provedorimagem.h" 

int main(int argc, char *argv[]) 
{ 
    QGuiApplication app(argc, argv); 

    qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem"); 

    QQmlApplicationEngine engine; 

    provedorImagem *provedorImg = new provedorImagem; 

    engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg); 

    engine.addImageProvider("provedor", provedorImg); 

    engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 

    return app.exec(); 
} 

main.qml

import QtQuick 2.4 
import QtQuick.Window 2.2 
import QtQuick.Controls 1.3 
import QtMultimedia 5.4 

import ProcessaImagemQml 1.0 

Window { 
    visible: true 

    width: 360 
    height: 640 

    maximumHeight: 640 
    minimumHeight: 640 

    maximumWidth: 360 
    minimumWidth: 360 

    title: "Camera Preview Test" 

    Rectangle { 
     id: principal 

     anchors.fill: parent 

     ProcessaImagem { 
      id: processaImagem 

      caminhoImagem: camera.caminhoPreview 
      caminhoSalvar: camera.caminhoSalvar 
      rectRecorte: camera.rectRecorte 
      tamanhoImagem: camera.tamanhoImagem 
      anguloOrientacaoCamera: camera.orientation 
      posicaoCamera: camera.position 

      onCaminhoImagemChanged: { 
       rectRecorte = cameraView.mapRectToSource(Qt.rect(cameraView.x, cameraView.y, cameraView.width, cameraView.height)); 
       tamanhoImagem = Qt.size(cameraView.sourceRect.width, cameraView.sourceRect.height); 
       ProvedorImagem.carregaImagem(processaImagem.carregaImagem()); 
      } 

      onCaminhoSalvarChanged: { 
       removeImagemSalva(); 
      } 
     } 

     Rectangle { 
      id: cameraRectangle 

      width: parent.width 
      height: parent.width 

      anchors.top: parent.top 

      color: "lightGrey" 

      visible: true 

      Camera { 
       id: camera 

       property string caminhoPreview: "" 
       property string caminhoSalvar: "" 
       property int numeroImagem: 0 

       captureMode: Camera.CaptureStillImage 

       imageCapture { 
        onImageCaptured: { 
         camera.caminhoPreview = preview; 

         camera.stop(); 

         imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString(); 

         camera.numeroImagem = camera.numeroImagem + 1; 

         imagemPreviewRectangle.visible = true; 

         cameraRectangle.visible = false; 
        } 

        onImageSaved: { 
         camera.caminhoSalvar = path; 
        } 
       } 
      } 

      VideoOutput { 
       id: cameraView 

       visible: true 

       focus: visible 

       anchors.fill: parent 

       source: camera 
       orientation: camera.orientation 
       fillMode: VideoOutput.PreserveAspectCrop 
      } 
     } 

     Rectangle { 
      id: imagemPreviewRectangle 

      width: parent.width 
      height: parent.width 

      anchors.top: parent.top 

      color: "lightGrey" 

      visible: false 

      Image { 
       id: imagemPreview 

       fillMode: Image.PreserveAspectFit 

       anchors.fill: parent 
      } 
     } 

     Rectangle { 
      id: controleRectangle 

      width: parent.width 
      height: parent.height - cameraRectangle.height 

      color: "grey" 

      anchors.top: cameraRectangle.bottom 

      Button { 
       id: tirarFotoButton 

       text: "Tirar foto" 

       anchors.left: parent.left 
       anchors.top: parent.top 

       onClicked: { 
        camera.imageCapture.capture(); 
       } 
      } 

      Button { 
       id: novaFotoButton 

       text: "Tirar nova foto" 

       anchors.right: parent.right 
       anchors.top: parent.top 

       onClicked: { 
        camera.start(); 

        imagemPreviewRectangle.visible = false; 

        cameraRectangle.visible = true; 
       } 
      } 
     } 
    } 
} 

processaimagem.h

#ifndef PROCESSAIMAGEM_H 
#define PROCESSAIMAGEM_H 

#include <QObject> 
#include <QImage> 
#include <QQmlEngine> 
#include <QQmlContext> 
#include <QQuickImageProvider> 
#include <QFile> 

#include "provedorimagem.h" 

class processaImagem : public QObject 
{ 
    Q_OBJECT 

    Q_PROPERTY(QString caminhoImagem READ caminhoImagem WRITE setCaminhoImagem NOTIFY caminhoImagemChanged) 
    Q_PROPERTY(QString caminhoSalvar READ caminhoSalvar WRITE setCaminhoSalvar NOTIFY caminhoSalvarChanged) 
    Q_PROPERTY(QRect rectRecorte READ rectRecorte WRITE setRectRecorte NOTIFY rectRecorteChanged) 
    Q_PROPERTY(QSize tamanhoImagem READ tamanhoImagem WRITE setTamanhoImagem NOTIFY tamanhoImagemChanged) 
    Q_PROPERTY(int anguloOrientacaoCamera READ anguloOrientacaoCamera WRITE setAnguloOrientacaoCamera NOTIFY anguloOrientacaoCameraChanged) 
    Q_PROPERTY(int posicaoCamera READ posicaoCamera WRITE setPosicaoCamera NOTIFY posicaoCameraChanged) 

public slots: 
    QImage carregaImagem(); 
    void removeImagemSalva(); 

public: 
    processaImagem(QObject *parent = 0); 

    QString caminhoImagem() const; 
    void setCaminhoImagem(const QString valor); 

    QString caminhoSalvar() const; 
    void setCaminhoSalvar(const QString valor); 

    QRect rectRecorte() const; 
    void setRectRecorte(const QRect valor); 

    QSize tamanhoImagem() const; 
    void setTamanhoImagem(const QSize valor); 

    int anguloOrientacaoCamera() const; 
    void setAnguloOrientacaoCamera(const int valor); 

    int posicaoCamera() const; 
    void setPosicaoCamera(const int valor); 

private: 
    QString p_caminhoImagem = ""; 
    QString p_caminhoSalvar = ""; 
    QRect p_rectRecorte = QRect(0, 0, 0, 0); 
    QSize p_tamanhoImagem = QSize(0, 0); 
    int p_anguloOrientacaoCamera = 0; 
    int p_posicaoCamera = 0; 

signals: 
    void caminhoImagemChanged(); 
    void caminhoSalvarChanged(); 
    void rectRecorteChanged(); 
    void tamanhoImagemChanged(); 
    void anguloOrientacaoCameraChanged(); 
    void posicaoCameraChanged(); 
}; 

#endif // PROCESSAIMAGEM_H 

processaimagem.cpp

#include "processaimagem.h" 

#include <QDebug> 

processaImagem::processaImagem(QObject *parent) 
{ 

} 

QImage processaImagem::carregaImagem() 
{ 
    QUrl caminhoImagem(p_caminhoImagem); 
    QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine(); 
    QQmlImageProviderBase *imageProviderBase = engine->imageProvider(caminhoImagem.host()); 
    QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase); 


    QSize imageSize; 
    QString imageId = caminhoImagem.path().remove(0, 1); 
    QImage imagem = imageProvider->requestImage(imageId, &imageSize, imageSize); 

    if(imagem.isNull()) 
    { 
     qDebug() << "Erro ao carregar a imagem"; 
     imagem = QImage(); 
    } 
    else 
    { 
     if((p_anguloOrientacaoCamera == 90) || (p_anguloOrientacaoCamera == 270)) 
     { 
      int larguraImagem = p_tamanhoImagem.width(); 
      int alturaImagem = p_tamanhoImagem.height(); 

      p_tamanhoImagem.setWidth(alturaImagem); 
      p_tamanhoImagem.setHeight(larguraImagem); 

      int recorteX = p_rectRecorte.x(); 
      int recorteY = p_rectRecorte.y(); 
      int recorteLargura = p_rectRecorte.width(); 
      int recorteAltura = p_rectRecorte.height(); 

      p_rectRecorte.setRect(recorteY, recorteX, recorteAltura, recorteLargura); 

      if(imagem.size().width() > imagem.size().height()) 
      { 
       QTransform rotacao; 
       rotacao.rotate(360 - p_anguloOrientacaoCamera); 
       imagem = imagem.transformed(rotacao); 

       qDebug() << "Rodou"; 
      } 
     } 

     if(imagem.width() != p_tamanhoImagem.width()) 
     { 
      imagem = imagem.scaled(p_tamanhoImagem); 
     } 

     imagem = imagem.copy(p_rectRecorte); 
    } 

    return imagem; 
} 

void processaImagem::removeImagemSalva() 
{ 
    QFile::remove(p_caminhoSalvar); 
} 

QString processaImagem::caminhoImagem() const 
{ 
    return p_caminhoImagem; 
} 

void processaImagem::setCaminhoImagem(const QString valor) 
{ 
    if (valor != p_caminhoImagem) 
    { 
     p_caminhoImagem = valor; 
     emit caminhoImagemChanged(); 
    } 
} 

QString processaImagem::caminhoSalvar() const 
{ 
    return p_caminhoSalvar; 
} 

void processaImagem::setCaminhoSalvar(const QString valor) 
{ 
    if (valor != p_caminhoSalvar) 
    { 
     p_caminhoSalvar = valor; 
     emit caminhoSalvarChanged(); 
    } 
} 

QRect processaImagem::rectRecorte() const 
{ 
    return p_rectRecorte; 
} 

void processaImagem::setRectRecorte(const QRect valor) 
{ 
    bool alterou = false; 

    if (valor.x() != p_rectRecorte.x()) 
    { 
     p_rectRecorte.setX(valor.x()); 
     alterou = true; 
    } 

    if (valor.y() != p_rectRecorte.y()) 
    { 
     p_rectRecorte.setY(valor.y()); 
     alterou = true; 
    } 

    if (valor.width() != p_rectRecorte.width()) 
    { 
     p_rectRecorte.setWidth(valor.width()); 
     alterou = true; 
    } 

    if (valor.height() != p_rectRecorte.height()) 
    { 
     p_rectRecorte.setHeight(valor.height()); 
     alterou = true; 
    } 

    if(alterou) 
    { 
     emit rectRecorteChanged(); 
    } 
} 

QSize processaImagem::tamanhoImagem() const 
{ 
    return p_tamanhoImagem; 
} 

void processaImagem::setTamanhoImagem(const QSize valor) 
{ 
    bool alterou = false; 

    if (valor.width() != p_tamanhoImagem.width()) 
    { 
     p_tamanhoImagem.setWidth(valor.width()); 
     alterou = true; 
    } 

    if (valor.height() != p_tamanhoImagem.height()) 
    { 
     p_tamanhoImagem.setHeight(valor.height()); 
     alterou = true; 
    } 

    if(alterou) 
    { 
     emit tamanhoImagemChanged(); 
    } 
} 

int processaImagem::anguloOrientacaoCamera() const 
{ 
    return p_anguloOrientacaoCamera; 
} 

void processaImagem::setAnguloOrientacaoCamera(const int valor) 
{ 
    if (valor != p_anguloOrientacaoCamera) 
    { 
     p_anguloOrientacaoCamera = valor; 
     emit anguloOrientacaoCameraChanged(); 
    } 
} 

int processaImagem::posicaoCamera() const 
{ 
    return p_posicaoCamera; 
} 

void processaImagem::setPosicaoCamera(const int valor) 
{ 
    if (valor != p_posicaoCamera) 
    { 
     p_posicaoCamera = valor; 
     emit posicaoCameraChanged(); 
    } 
} 

provedorimagem.h

#ifndef PROVEDORIMAGEM_H 
#define PROVEDORIMAGEM_H 

#include <QObject> 
#include <QImage> 
#include <QQuickImageProvider> 

class provedorImagem : public QObject, public QQuickImageProvider 
{ 
    Q_OBJECT 

public: 
    provedorImagem(); 

    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize); 

public slots: 
    void carregaImagem(QImage imagemRecebida); 

private: 
    QImage imagem; 
}; 

#endif // PROVEDORIMAGEM_H 

provedorimagem.cpp

#include "provedorimagem.h" 

#include <QDebug> 

provedorImagem::provedorImagem() : QQuickImageProvider(QQuickImageProvider::Image) 
{ 

} 

QImage provedorImagem::requestImage(const QString &id, QSize *size, const QSize &requestedSize) 
{ 
    if(imagem.isNull()) 
    { 
     qDebug() << "Erro ao prover a imagem"; 
    } 

    return imagem; 
} 

void provedorImagem::carregaImagem(QImage imagemRecebida) 
{ 
    imagem = imagemRecebida; 
} 
+3

Благодарим вас за сообщение. Тем не менее, пример будет полезен при написании с английским классом и именами участников. Не все в мире читают Portugese ... –

+0

Я не писал это на английском, потому что это часть моего приложения, и это приложение написано на португальском языке. – GuiDupas

+0

@KlaasvanGend Я не понял, откуда эта переменная исходит: 'imagemEditada_'. GuiDupas, пожалуйста, помогите. –

 Смежные вопросы

  • Нет связанных вопросов^_^