QML使用Image加载图片,在图片上做标记并保存标记

qml:我使用了一个Image来显示我电脑桌面的一个图片,然后我使用Canvas去做标记,在鼠标抬起的时候我保存了标记在桌面的test.png上面,这里我使用的是C++方式去保存,因为我没找到什么比较好的QML方式保存

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.12

Item {
    visible: true
    width: 1920
    height: 1080

    Image {
        id: images
        source: "file:///C:/Users/test/Desktop/test.png" // 替换为你要显示的图片路径
        //等比放大 控件填充整个父布局
        //anchors.fill: parent
        //fillMode: Image.PreserveAspectFit
        //原始大小
        width: images.sourceSize.width
        height: images.sourceSize.height
        fillMode: Image.None

        Canvas {
               id: canvas
               //元素将会完全填充其父元素,使其大小与父元素保持一致。
               anchors.fill: parent

               // 绘制事件
               onPaint: {
                   var ctx = getContext("2d");

                   // 设置绘制样式
                   ctx.strokeStyle = "red";
                   ctx.lineWidth = 1;

                   // 绘制路径
                   ctx.beginPath();
                   for (var i = 0; i < mouseArea.drawingPoints.length; i++) {
                       var point = mouseArea.drawingPoints[i];
                       if (i === 0) {
                           //绘制起点
                           ctx.moveTo(point.x, point.y);
                       } else {
                           //用于从当前绘制点绘制一条直线到指定的坐标
                           ctx.lineTo(point.x, point.y);
                       }
                   }
                   ctx.stroke();
               }
           }

           MouseArea {
               id: mouseArea
               anchors.fill: parent
               hoverEnabled: true

               property var drawingPoints: []

               // 处理按下事件
               onPressed: {
                   y_log("MouseArea====","onPressed====")
                   drawingPoints.push(0,Qt.point(mouse.x, mouse.y));
                   y_log(mouse.x,mouse.y)
               }

               // 处理移动事件
               onPositionChanged: {
                   //左键 一般触屏也是这个状态值
                   if (mouse.buttons === Qt.LeftButton) {
                       drawingPoints.push(Qt.point(mouse.x, mouse.y));
                       canvas.requestPaint();
                   }
               }

               onReleased: {
                   //先保存
                   var filePath = images.source.toString().replace("file:///", "")
                   y_log("filePath====",filePath)
                   mainactivity.saveImage(filePath, mouseArea.drawingPoints, filePath);
                   //抬起的时候清空数组
                   drawingPoints = []
               }
           }



    }
}

 .h文件

#pragma once
#pragma once
#include 
#include 
#include 
#include 
class MainActivity : public QObject
{
    Q_OBJECT
public:
    MainActivity(QGuiApplication& app, QQmlApplicationEngine &engine);
    //保存标记到指定的图片上
    Q_INVOKABLE void saveImage(const QString &imagePath, const QVariantList &drawingPoints, const QString &savePath);
private:
    QGuiApplication *m_app;
    QQmlApplicationEngine *m_engine;
};

 .c文件


#include "QImage"
#include "QPainter"
#include "mainactivity.h"
#include "QDebug"
#include "QProcess"

MainActivity::MainActivity(QGuiApplication &app, QQmlApplicationEngine& engine)
{
    m_app = &app;
    m_engine = &engine;
}

void MainActivity::saveImage(const QString &imagePath, const QVariantList &drawingPoints, const QString &savePath)
{
    QImage image(imagePath);
    qDebug() << "Image path:" << imagePath;
    qDebug() << "Image savePath:"<< savePath;

    if (image.isNull()) {
        qDebug() << "Image loading failed!";
        return;
    }

    //将图片的颜色空间设置为RGB 如果不设置的话,那么绘制出来的标记可能就是黑色
    image = image.convertToFormat(QImage::Format_RGB888);

    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(QPen(Qt::red, 1));

    qDebug() << "drawingPoints==:" << drawingPoints.size();

    //避免从左上角到第一个点的直线绘制
    int startPointIndex = 0;
    if (!drawingPoints.isEmpty()) {
        for (int i = 0; i < drawingPoints.size(); ++i) {
            const QVariant& point = drawingPoints[i];
            QPointF pt = point.toPointF();
            if (pt != QPointF(0, 0)) {
                startPointIndex = i;
                break;
            }
        }
    }

    for (int i = startPointIndex + 1; i < drawingPoints.size(); ++i) {
        const QVariant& prevPoint = drawingPoints[i - 1];
        const QVariant& currPoint = drawingPoints[i];
        QPointF prevPt = prevPoint.toPointF();
        QPointF currPt = currPoint.toPointF();

        painter.drawLine(prevPt, currPt);
    }

    qDebug() << "Image savePath2:"<< savePath;
    if (!image.save(savePath)) {
        qDebug() << "Image saving failed!";
    }else {
        qDebug() << "Image saved successfully!";
    }
}

 main.cpp:

#include 
#include 
#include 
#include 
#include 
#include 
#include "mainactivity.h"
#include "QSettings"

int main(int argc, char *argv[])
{
    qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    //解决窗口拖拽时闪烁的问题
    QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);

    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    app.setOrganizationName("test");

    //将QmlLanguage中的所有函数暴露给qml调用
    MainActivity mainactivity(app, engine);
    engine.rootContext()->setContextProperty("mainactivity", &mainactivity);
    const QUrl url(QStringLiteral("qrc:/Activity_layout.qml"));
    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();
}

 我直接在Image上绘制,这个返回键你们不用在意,这是我项目代码里面的,我懒得删QML使用Image加载图片,在图片上做标记并保存标记_第1张图片

 本地保存的效果:这是我在画了以后打开桌面test.png的效果

QML使用Image加载图片,在图片上做标记并保存标记_第2张图片

 这里最主要的是图片原始大小,因为在保存的时候,加载的QImage就是原始大小,如果你在布局里面直接写放大到全屏,到时候保存下来的标记可能位置有偏移

你可能感兴趣的:(QML)