Save QPainter after called update - qt

I want to draw straight lines on qml , but every time I draw a line, the previous disappears, I wonder if it has any thing to do with the update method, any ways to solve this problem.
main.qml
MouseArea{
id:fidpoint
anchors.fill: parent
onPressed: {
switch(addstate.currentText){
case 'Track':
map.setTstart(mouseX,mouseY);
draw_line.setColor("black");
draw_line.setStart(Qt.point(mouseX,mouseY));
draw_line.setEnd(Qt.point(mouseX,mouseY));
draw_line.update();
break;
}
}
onReleased: {
switch(addstate.currentText){
case 'Track':
map.addTrack(mouseX,mouseY);
draw_line.setColor("black");
draw_line.setEnd(Qt.point(mouseX,mouseY));
draw_line.update();
break;
}
}
onPositionChanged: {
switch(addstate.currentText){
case 'Track':
draw_line.setColor("black");
draw_line.setEnd(Qt.point(mouseX,mouseY));
draw_line.update();
break;
}
}
}
draw_line is the Object's id that I registered to qml from main.cpp
paint.cpp
void Paint::paint(QPainter *painter)
{
QPen pen(m_color, 2);
painter->setPen(pen);
painter->setRenderHint(QPainter::Antialiasing,true);
painter->drawLine(startNode,endNode);
}
paint is the class that inherits from QQuickPaintedItem

A possible option would be to create an image and save the changes there, but this would solve your problem in the short term. A better option is that draw_line draw only one line, then add it as a child of the item you want the canvas to be.
lineitem.h
#ifndef LINEITEM_H
#define LINEITEM_H
#include <QQuickPaintedItem>
class LineItem: public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QPoint startPos READ startPos WRITE setStartPos NOTIFY startPosChanged)
Q_PROPERTY(QPoint endPos READ endPos WRITE setEndPos NOTIFY endPosChanged)
Q_PROPERTY(QColor lineColor READ lineColor WRITE setLineColor NOTIFY lineColorChanged)
public:
using QQuickPaintedItem::QQuickPaintedItem;
void paint(QPainter *painter);
QPoint startPos() const;
void setStartPos(const QPoint &startPos);
QPoint endPos() const;
void setEndPos(const QPoint &endPos);
QColor lineColor() const;
void setLineColor(const QColor &lineColor);
signals:
void startPosChanged();
void endPosChanged();
void lineColorChanged();
private:
QPoint m_startPos;
QPoint m_endPos;
QColor m_lineColor;
};
#endif // LINEITEM_H
lineitem.cpp
#include "lineitem.h"
#include <QPainter>
void LineItem::paint(QPainter *painter)
{
painter->setRenderHint(QPainter::Antialiasing, true);
QPen pen(m_lineColor, 2);
painter->setPen(pen);
painter->drawLine(m_startPos, m_endPos);
}
QPoint LineItem::startPos() const
{
return m_startPos;
}
void LineItem::setStartPos(const QPoint &startPos)
{
if(m_startPos == startPos)
return;
m_startPos = startPos;
emit startPosChanged();
update();
}
QPoint LineItem::endPos() const
{
return m_endPos;
}
void LineItem::setEndPos(const QPoint &endPos)
{
if(m_endPos == endPos)
return;
m_endPos = endPos;
emit endPosChanged();
update();
}
QColor LineItem::lineColor() const
{
return m_lineColor;
}
void LineItem::setLineColor(const QColor &lineColor)
{
if(m_lineColor == lineColor)
return;
m_lineColor = lineColor;
emit lineColorChanged();
update();
}
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import com.eyllanesc.org 1.0
Window {
id: win
visible: true
width: 640
height: 480
title: qsTr("Hello World")
property LineItem currentItem: null
Rectangle{
id: canvas
anchors.fill: parent
MouseArea{
anchors.fill: parent
onPressed: {
currentItem = create_lineitem(canvas)
currentItem.lineColor = "green"
currentItem.anchors.fill = canvas
currentItem.startPos = Qt.point(mouseX,mouseY)
currentItem.endPos = Qt.point(mouseX,mouseY)
}
onReleased: currentItem.endPos = Qt.point(mouseX,mouseY)
onPositionChanged: currentItem.endPos = Qt.point(mouseX,mouseY)
}
}
function create_lineitem(parentItem, color) {
return Qt.createQmlObject('import com.eyllanesc.org 1.0; LineItem{}',
parentItem);
}
}
main.cpp
#include "lineitem.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<LineItem>("com.eyllanesc.org", 1, 0, "LineItem");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
The complete example can be found in the following link.

Related

Text gets missaligned when using Qt TextTable with TextArea using QtQuick.Controls 1.12

I have a problem where I am using a TextArea in Qml. A C++ Model holds a reference to that TextArea.
When I insert a QTextTable in the C++ model it all fine until the user enters some text. After the user manually edits a few cells and writes some text in it, it gets all messed up. Does anyone know anything on how to solve it?
I also have other functions with are working perfectly. So I would guess there is nothing wrong with the connection between the c++ model and the textarea.
Here is the Documenthandler.h
#include <QQuickTextDocument>
#include <QtGui/QTextCharFormat>
#include <QtCore/QTextCodec>
#include <qqmlfile.h>
QT_BEGIN_NAMESPACE
class QTextDocument;
QT_END_NAMESPACE
class DocumentHandler : public QObject
{
Q_OBJECT
Q_ENUMS(HAlignment)
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
public:
DocumentHandler();
Q_INVOKABLE void createTable(int columns ,int rows);
QQuickItem *target() { return m_target; }
void setTarget(QQuickItem *target);
QString text() const;
public Q_SLOTS:
void setText(const QString &arg);
Q_SIGNALS:
void targetChanged();
void textChanged();
void error(QString message);
private:
QTextCursor textCursor() const;
QQuickItem *m_target;
QTextDocument *m_doc;
QString m_text;
};
Here is the documenthandler.cpp
in the "createTable" function I create the table
#include "documenthandler.h"
#include <QtGui/QTextDocument>
#include <QtGui/QTextList>
#include <QtGui/QTextTable>
#include <QtGui/QTextCursor>
#include <QtGui/QFontDatabase>
#include <QtCore/QFileInfo>
DocumentHandler::DocumentHandler()
: m_target(0)
, m_doc(0)
{
}
void DocumentHandler::setTarget(QQuickItem *target)
{
m_doc = 0;
m_target = target;
if (!m_target)
return;
QVariant doc = m_target->property("textDocument");
if (doc.canConvert<QQuickTextDocument*>()) {
QQuickTextDocument *qqdoc = doc.value<QQuickTextDocument*>();
if (qqdoc)
m_doc = qqdoc->textDocument();
}
emit targetChanged();
}
void DocumentHandler::setText(const QString &arg)
{
if (m_text != arg) {
m_text = arg;
emit textChanged();
}
}
QString DocumentHandler::text() const
{
return m_text;
}
QTextCursor DocumentHandler::textCursor() const
{
if (!m_doc)
return QTextCursor();
QTextCursor cursor = QTextCursor(m_doc);
return cursor;
}
void DocumentHandler::createTable(int columns , int rows)
{
QTextCursor cursor = textCursor();
if (cursor.isNull())
return;
cursor.insertTable(rows,columns);
}
Here is the main qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 1.6
import DocumentHandler 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Button
{
id:btn
text:"test"
onClicked: document.createTable(5,5);
}
TextArea {
Accessible.name: "document"
id: tooltip_area
selectByMouse: true
anchors.left:parent.left
anchors.right:parent.right
anchors.top: btn.bottom
anchors.bottom: parent.bottom
baseUrl: "qrc:/"
text: document.text
textFormat: Qt.RichText
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Component.onCompleted: forceActiveFocus()
}
DocumentHandler{
id: document
target: tooltip_area
}
}
here is the main function, there is nothing special except I register the QML Type
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "documenthandler.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
qmlRegisterType<DocumentHandler>("DocumentHandler",1,0,"DocumentHandler");
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
This is how it looks after filling up some cells
So I solved it by just selecting everything and deselecting when the text changes. Theoretically I only need to do it when I am in a Table Block.
onTextChanged:
{
if(recoursionlock)
{
recoursionlock =false;
var curpos = tooltip_area.cursorPosition;
var select_start = tooltip_area.selectionStart;
var select_end = tooltip_area.selectionEnd;
selectAll();
deselect();
if(curpos !== -1 && curpos >= tooltip_area.text.lenght)
tooltip_area.cursorPosition = curpos;
else
tooltip_area.select(select_start,select_end)
recoursionlock = true;
}
}

I bind a custom FBO, but what I draw goes beyond it

I've made a simple testcase. What I do, in short:
I have a QQuickFramebufferObject subclass called MyItem. It uses the CombinedDepthStencil Attachment type.
I create an instance of MyItem on window hover and destroy it on window unhover
In MyItemRenderer::render() I create a local FBO and draw a triangle to it
This local FBO uses a custom FBO wrapper class instead of QOpenGLFramebufferObject, to narrow down the problem. The problem occurs with QOpenGLFramebufferObject too, though.
The expected behavior is that nothing should ever be drawn to the window. But instead, on the second time you hover the window (after launching the app), the triangle is drawn to the window.
My code:
main.cpp:
#include <QGuiApplication>
#include <QQuickView>
#include <QQuickWindow>
#include <QQuickFramebufferObject>
#include <QOpenGLFramebufferObject>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
#include "fbo.h"
class MyItem : public QQuickFramebufferObject {
Q_OBJECT
public:
Renderer* createRenderer() const;
};
class MyItemRenderer : public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions {
public:
MyItemRenderer() {
initializeOpenGLFunctions();
m_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shader.vert.glsl");
m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shader.frag.glsl");
m_program.link();
}
void render() {
glClearColor(0, 0, 0, 0);
glDisable(GL_DEPTH_TEST);
Fbo fbo(m_size);
m_program.bind();
fbo.bind();
glClear(GL_COLOR_BUFFER_BIT);
paintGeometry();
framebufferObject()->bind();
m_window->resetOpenGLState();
}
void paintGeometry() {
QVector<QVector2D> vertices = { QVector2D(0, 0), QVector2D(1, 0), QVector2D(1, 1) };
m_program.enableAttributeArray("aPos");
m_program.setAttributeArray("aPos", vertices.constData());
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
m_program.disableAttributeArray("aPos");
}
QOpenGLFramebufferObject* createFramebufferObject(const QSize &size) {
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
return new QOpenGLFramebufferObject(size, format);
}
private:
QOpenGLShaderProgram m_program;
QQuickWindow* m_window;
QSize m_size;
protected:
void synchronize(QQuickFramebufferObject* qqfbo) {
MyItem* parentItem = (MyItem*)qqfbo;
m_window = parentItem->window();
m_size = QSize(parentItem->width(), parentItem->height());
}
};
QQuickFramebufferObject::Renderer* MyItem::createRenderer() const {
return new MyItemRenderer();
}
int main(int argc, char **argv) {
QGuiApplication app(argc, argv);
qmlRegisterType<MyItem>("MyItem", 1, 0, "MyItem");
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.show();
return app.exec();
}
#include "main.moc"
main.qml:
import QtQuick 2.0
import MyItem 1.0
Item {
width: 400
height: 400
id: root
Loader {
active: mouseArea.containsMouse
sourceComponent: MyItem {
parent: root
anchors.fill: parent
}
}
MouseArea {
id: mouseArea
hoverEnabled: true
anchors.fill: parent
}
}
shader.frag.glsl:
void main() {
gl_FragColor = vec4(0.40, 1.0, 0.0, 1.0);
}
shader.vert.glsl:
attribute highp vec2 aPos;
void main() {
gl_Position = vec4(aPos, 0.0, 1.0);
}
fbo.h:
#ifndef FBO_H
#define FBO_H
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
class Fbo : public QOpenGLFunctions {
public:
Fbo(const QSize &size)
: m_colorAttachment(QOpenGLTexture::Target2D)
{
initializeOpenGLFunctions();
glGenFramebuffers(1, &m_id);
m_colorAttachment.setSize(size.width(), size.height());
m_colorAttachment.setFormat(QOpenGLTexture::RGBA8_UNorm);
m_colorAttachment.allocateStorage();
bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorAttachment.textureId(), 0);
}
~Fbo() {
glDeleteFramebuffers(1, &m_id);
}
void bind() {
glBindFramebuffer(GL_FRAMEBUFFER, m_id);
}
private:
GLuint m_id;
QOpenGLTexture m_colorAttachment;
};
#endif
Any ideas?
Note that I've ran the testcase in the CodeXL OpenGL debugger and it has found no OpenGL errors. Same with Qt's QOpenGLDebugLogger mechanism.

Drawing in QQuickFramebufferObject via texture taken from an Item. It fails unless I repaint/update constantly

What my code does, in short:
Create a simple Rectangle named rect, with layer.enabled: true.
Pass rect to an instance of my QQuickFramebufferObject subclass called itemSnapshotter
In synchronize, take a pointer to the texture provided by rect
In render, draw a rectangle textured with the texture I took
When main.qml finishes loading, call itemSnapshotter.update(); for the first and only time.
The problem is that the QQFBO draws nothing, unless I uncomment the update call at the end of render(). Any idea why?
My code:
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickFramebufferObject>
#include <QOpenGLFramebufferObject>
#include <QSGTextureProvider>
#include <QObject>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QQuickWindow>
#include <QOpenGLFunctions>
// propertyhelper.h is from http://syncor.blogspot.bg/2014/11/qt-auto-property.html
#include "propertyhelper.h"
class ItemSnapshotter : public QQuickFramebufferObject {
Q_OBJECT
AUTO_PROPERTY(QQuickItem*, sourceItem)
public:
Renderer *createRenderer() const;
};
class ItemSnapshotterRenderer
: public QObject
, public QQuickFramebufferObject::Renderer
, protected QOpenGLFunctions
{
Q_OBJECT
public:
ItemSnapshotterRenderer() {
initializeOpenGLFunctions();
initShader();
createGeometry();
}
void createGeometry() {
m_vertices << QVector2D(0, 0) << QVector2D(0, 1) << QVector2D(1, 1);
m_vertices << QVector2D(0, 0) << QVector2D(1, 0) << QVector2D(1, 1);
}
void initShader() {
m_shaderProgram.addShaderFromSourceFile(
QOpenGLShader::Vertex, ":/PassThrough.vert.glsl");
m_shaderProgram.addShaderFromSourceFile(
QOpenGLShader::Fragment, ":/PassThrough.frag.glsl");
m_shaderProgram.link();
m_shaderProgram.bind();
glActiveTexture(GL_TEXTURE0);
m_shaderProgram.setUniformValue("uTex", 0);
}
void prepareShader() {
m_shaderProgram.enableAttributeArray("aPos");
m_shaderProgram.setAttributeArray("aPos", m_vertices.constData());
m_shaderProgram.bind();
}
void render() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
prepareShader();
m_tex->bind();
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());
m_window->resetOpenGLState();
//update();
}
void synchronize(QQuickFramebufferObject* qqfbo){
auto parentItem = (ItemSnapshotter*)qqfbo;
m_window = parentItem->window();
copyTexture(*parentItem);
}
void copyTexture(const ItemSnapshotter &srcItem) {
QQuickItem* sourceItem = srcItem.sourceItem();
QSGTextureProvider* sourceTexProvider = sourceItem->textureProvider();
m_tex = sourceTexProvider->texture();
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
qDebug("\tgl error: 0x%x", err, 0, 16);
}
}
QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) {
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); // TODO simpler format
return new QOpenGLFramebufferObject(size, format);
}
private:
QOpenGLShaderProgram m_shaderProgram;
QQuickWindow* m_window;
QSGTexture* m_tex;
QVector<QVector2D> m_vertices;
};
QQuickFramebufferObject::Renderer *ItemSnapshotter::createRenderer() const {
return new ItemSnapshotterRenderer();
}
int main(int argc, char *argv[]) {
qmlRegisterType<ItemSnapshotter>("ItemSnapshotter", 1, 0, "ItemSnapshotter");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
#include "main.moc"
main.qml:
import QtQuick 2.6
import QtQuick.Window 2.2
import ItemSnapshotter 1.0
Window {
visible: true
width: 640
height: 480
Row {
Rectangle {
layer.enabled: true
id: rect
width: 100
height: 100
color: "red"
border.color: "black"
}
ItemSnapshotter {
id: itemSnapshotter
sourceItem: rect
width: sourceItem.width
height: sourceItem.height
}
}
Component.onCompleted: {
itemSnapshotter.update();
}
}
PassThrough.frag.glsl:
varying highp vec2 vTexCoord;
uniform sampler2D uTex;
void main() {
gl_FragColor = texture2D(uTex, vTexCoord);
}
PassThrough.vert.glsl:
attribute highp vec2 aPos;
varying highp vec2 vTexCoord;
void main() {
gl_Position = vec4(aPos, 0.0, 1.0);
vTexCoord = aPos;
}

QML Camera - take a Square photo

How can I take a photo using Camera in QML but with custom dimensions, like a square photo for example? I am trying to implement it with QQuickImageProvider but I am not understanding why it is not working.
QML code
Camera {
id: camera
captureMode: Camera.CaptureStillImage
imageCapture {
onImageCaptured: {
manipulaImagem.imagem = preview;
previewImage.source = "image://ProvedorImagens/" + 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
}
I am trying to resolve this problem by 2 ways:
First:
QImage manipulaImagem::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
QUrl caminhoImagem(id);
QString imageId = caminhoImagem.path().remove(0, 1);
QImage imagem1(id);
if(imagem1.isNull())
{
qDebug() << "Erro";
}
else
{
qDebug() << "OK";
}
return imagem1;
}
I call this method from QML using a image provider: previewImage.source = "image://ProvedorImagens/" + preview;
In this function using QImage imagem1(id) or QImage imagem1(imageId), both return me a NULL image.
It returns me message: QML Image: Failed to get image from provider: image://provedorimagens/image://camera/preview_1
The other way is another function:
QImage manipulaImagem::recortarFotoPerfil(const QString &imagem)
{
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);
if(imagem1.isNull())
{
qDebug() << "Erro";
}
else
{
qDebug() << "OK";
}
return imagem1;
}
This function gets the image but when I return it I receive a message:
Error: Cannot assign QImage to QUrl
I call this function directly from QML:
previewImage.source = manipulaImagem.recortarFotoPerfil(preview);
Thanks for the help.
Answering my own question
Problem solved. Here is the solution step by step:
1 - Create a class that inherits from QQuickImageProvider and QObject and inside it create a Image member (QImage) that is the image to be provided.
class provedorImagem : public QObject, public QQuickImageProvider
Implement the virtual requestImage method. This is the method that will return the image to Qml
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
Create a method to load the provider’s image to return
void provedorImagem::carregaImagem(QImage imagemRecebida)
{
imagem = imagemRecebida;
}
Now set it as the engine image provider in the main.cpp file
provedorImagem *provedorImg = new provedorImagem;
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
2 - Create another class that inherits from QObject.
class processaImagem : public QObject
Inside this class you must implement a method that will get the image from camera provider, perform the image modifications and return the modified image.
PS: The p_caminhoImagem is a property that I created inside the processaImagem class that receives the 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 - Now is the main part. The image requestImage provider method must receive the modified image from the processaImagem class to provide it to QML. To do it the provider class pointer must be accessible to the QML file, so, in the main.cpp file just make the pointer available to QML as a property
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
and register the processaImagem class as a QML type
qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem");
Now we link it inside the QML file
ProvedorImagem.carregaImagem(processaImagem.carregaImagem());
4 - It is done. Now just request the image from the provider:
imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString();
Here is the entire code:
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;
}

Pass QImage to QML

I am trying to pass a QImage to QML. Could someone help me? The code is below.
The problem is that all my attempts to make the image available for the image provider fail. I have tried using a Q_PROPERTY and a QImage member inside the class, but my provider always returns a null image when I try to access it to return.
How can I make the QImage available for the provider?
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;
}
When I use this I receive the following message:
Error: Cannot assign QImage to QUrl
I did not find anything to help me to solve this. How can I do that?
I have tried a different approach using the image provider as suggested by the links, but it still not working
Here is the code
.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
}
The output of this code is:
Loading image OK
Imagem is loaded
Request image: (image is null)
QML Image: Failed to get image from provider: image://provedorimagens/imagemEditada
What happens is that when I call the functions the image is not null, but when I try to return the QImage using the provider it cant return the image. I dont know why but for the image provider the image is null.
How could I solve that?
Answering my own question
Problem solved. Here is the solution step by step:
1 - Create a class that inherits from QQuickImageProvider and QObject and inside it create a Image member (QImage) that is the image to be provided.
class provedorImagem : public QObject, public QQuickImageProvider
Implement the virtual requestImage method. This is the method that will return the image to Qml
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
Create a method to load the provider’s image to return
void provedorImagem::carregaImagem(QImage imagemRecebida)
{
imagem = imagemRecebida;
}
Now set it as the engine image provider in the main.cpp file
provedorImagem *provedorImg = new provedorImagem;
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
2 - Create another class that inherits from QObject.
class processaImagem : public QObject
Inside this class you must implement a method that will get the image from camera provider, perform the image modifications and return the modified image.
PS: The p_caminhoImagem is a property that I created inside the processaImagem class that receives the 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 - Now is the main part. The image requestImage provider method must receive the modified image from the processaImagem class to provide it to QML. To do it the provider class pointer must be accessible to the QML file, so, in the main.cpp file just make the pointer available to QML as a property
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
and register the processaImagem class as a QML type
qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem");
Now we link it inside the QML file
ProvedorImagem.carregaImagem(processaImagem.carregaImagem());
4 - It is done. Now just request the image from the provider:
imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString();
Here is the entire code:
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;
}
Here's my code for converting a QImage to a QUrl. Once it's a QUrl you can easily pass it to QML:
QUrl imageToUrl(const QImage& image)
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "png");
QString base64 = QString::fromUtf8(byteArray.toBase64());
return QString("data:image/png;base64,") + base64;
}

Resources