QT- QT-lximagerEidtor图片编辑器

news2024/9/23 13:25:49

QT- QT-lximagerEidtor图片编辑器

  • 一、演示效果
  • 二、关键程序
  • 三、下载链接

功能如下:
1、缩放、旋转、翻转和调整图像大小
2、幻灯片
3、缩略图栏(左、上或下);不同的缩略图大小
4、Exif数据栏
5、内联图像重命名
6、自定义快捷方式
7、图像注释(箭头、矩形、圆形、数字)
8、最近的文件
9、上传图片(Imgur)
10、截屏

一、演示效果

在这里插入图片描述

二、关键程序

using namespace LxImage;

static bool hasXFixes() {
  int event_base, error_base;
  return XFixesQueryExtension(QX11Info::display(), &event_base, &error_base);
}

ScreenshotDialog::ScreenshotDialog(QWidget* parent, Qt::WindowFlags f): QDialog(parent, f), hasXfixes_(hasXFixes()) {
  ui.setupUi(this);
  Application* app = static_cast<Application*>(qApp);
  app->addWindow();
  if(!hasXfixes_) {
    ui.includeCursor->hide();
  }
}

ScreenshotDialog::~ScreenshotDialog() {
  Application* app = static_cast<Application*>(qApp);
  app->removeWindow();
}

void ScreenshotDialog::done(int r) {
  if(r == QDialog::Accepted) {
    hide();
    QDialog::done(r);
    XSync(QX11Info::display(), 0); // is this useful?

    int delay = ui.delay->value();
    if(delay == 0) {
      // NOTE:
      // Well, we need to give X and the window manager some time to
      // really hide our own dialog from the screen.
      // Nobody knows how long it will take, and there is no reliable
      // way to ensure that. Let's wait for 400 ms here for it.
      delay = 400;
    }
    else {
      delay *= 1000;
    }
    // the dialog object will be deleted in doScreenshot().
    QTimer::singleShot(delay, this, SLOT(doScreenshot()));
  }
  else {
    deleteLater();
  }
}

QRect ScreenshotDialog::windowFrame(WId wid) {
  QRect result;
  XWindowAttributes wa;
  if(XGetWindowAttributes(QX11Info::display(), wid, &wa)) {
    Window child;
    int x, y;
    // translate to root coordinate
    XTranslateCoordinates(QX11Info::display(), wid, wa.root, 0, 0, &x, &y, &child);
    //qDebug("%d, %d, %d, %d", x, y, wa.width, wa.height);
    result.setRect(x, y, wa.width, wa.height);

    // get the frame widths added by the window manager
    Atom atom = XInternAtom(QX11Info::display(), "_NET_FRAME_EXTENTS", false);
    unsigned long type, resultLen, rest;
    int format;
    unsigned char* data = nullptr;
    if(XGetWindowProperty(QX11Info::display(), wid, atom, 0, G_MAXLONG, false,
                          XA_CARDINAL, &type, &format, &resultLen, &rest, &data) == Success) {
    }
    if(data) {  // left, right, top, bottom
      long* offsets = reinterpret_cast<long*>(data);
      result.setLeft(result.left() - offsets[0]);
      result.setRight(result.right() + offsets[1]);
      result.setTop(result.top() - offsets[2]);
      result.setBottom(result.bottom() + offsets[3]);
      XFree(data);
    }
  }
  return result;
}

WId ScreenshotDialog::activeWindowId() {
  WId root = WId(QX11Info::appRootWindow());
  Atom atom = XInternAtom(QX11Info::display(), "_NET_ACTIVE_WINDOW", false);
  unsigned long type, resultLen, rest;
  int format;
  WId result = 0;
  unsigned char* data = nullptr;
  if(XGetWindowProperty(QX11Info::display(), root, atom, 0, 1, false,
                        XA_WINDOW, &type, &format, &resultLen, &rest, &data) == Success) {
    result = *reinterpret_cast<long*>(data);
    XFree(data);
  }
  return result;
}

QImage ScreenshotDialog::takeScreenshot(const WId& wid, const QRect& rect, bool takeCursor) {
  QImage image;
  QScreen *screen = QGuiApplication::primaryScreen();
  if(screen) {
    QPixmap pixmap = screen->grabWindow(wid, rect.x(), rect.y(), rect.width(), rect.height());
    image = pixmap.toImage();

    //call to hasXFixes() maybe executed here from cmd line with no gui mode (some day though, currently ignore cursor)
    if(takeCursor &&  hasXFixes()) {
      // capture the cursor if needed
      XFixesCursorImage* cursor = XFixesGetCursorImage(QX11Info::display());
      if(cursor) {
        if(cursor->pixels) {  // pixles should be an ARGB array
          QImage cursorImage;
          if(sizeof(long) == 4) {
            // FIXME: will we encounter byte-order problems here?
            cursorImage = QImage((uchar*)cursor->pixels, cursor->width, cursor->height, QImage::Format_ARGB32);
          }
          else { // XFixes returns long integers which is not 32 bit on 64 bit systems.
            long len = cursor->width * cursor->height;
            quint32* buf = new quint32[len];
            for(long i = 0; i < len; ++i) {
              buf[i] = (quint32)cursor->pixels[i];
            }
            cursorImage = QImage((uchar*)buf, cursor->width, cursor->height, QImage::Format_ARGB32, [](void* b) {
              delete[](quint32*)b;
            }, buf);
          }
          // paint the cursor on the current image
          QPainter painter(&image);
          painter.drawImage(cursor->x - cursor->xhot, cursor->y - cursor->yhot, cursorImage);
        }
        XFree(cursor);
      }
    }
  }
  return image;
}

void ScreenshotDialog::doScreenshot() {
  WId wid = 0;
  QRect rect{0, 0, -1, -1};

  wid = QApplication::desktop()->winId(); // get desktop window
  if(ui.currentWindow->isChecked()) {
    WId activeWid = activeWindowId();
    if(activeWid) {
      if(ui.includeFrame->isChecked()) {
        rect = windowFrame(activeWid);
      }
      else {
        wid = activeWid;
      }
    }
  }

  //using stored hasXfixes_ so avoid extra call to function later
  QImage image{takeScreenshot(wid, rect, hasXfixes_ && ui.includeCursor->isChecked())};

  if(ui.screenArea->isChecked() && !image.isNull()) {
    ScreenshotSelectArea selectArea(image);
    if(QDialog::Accepted == selectArea.exec()) {
      image = image.copy(selectArea.selectedArea());
    }
  }

  Application* app = static_cast<Application*>(qApp);
  MainWindow* window = app->createWindow();
  window->resize(app->settings().windowWidth(), app->settings().windowHeight());
  if(!image.isNull()) {
    window->pasteImage(image);
  }
  window->show();

  deleteLater(); // destroy ourself
}

static QString buildNumericFnPart() {
  //we may have many copies running with no gui, for example user presses hot keys fast
  //so they must have different file names to save, lets do it time + pid
  const auto now = QDateTime::currentDateTime().toMSecsSinceEpoch();
  const auto pid = getpid();
  return QStringLiteral("%1_%2").arg(now).arg(pid);
}

static QString getWindowName(WId wid) {
  QString result;
  if(wid) {
    static const char* atoms[] = {
      "WM_NAME",
      "_NET_WM_NAME",
      "STRING",
      "UTF8_STRING",
    };


    const auto display = QX11Info::display();

    Atom a = None, type;


    for(const auto& c : atoms) {
      if(None != (a = XInternAtom(display, c, true))) {
        int form;
        unsigned long remain, len;
        unsigned char *list;

        errno = 0;
        if(XGetWindowProperty(display, wid, a, 0, 1024, False, XA_STRING,
                              &type, &form, &len, &remain, &list) == Success) {

          if(list && *list) {

            std::string dump((const char*)list);
            std::stringstream ss;
            for(const auto& sym : dump) {
              if(std::isalnum(sym)) {
                ss.put(sym);
              }
            }
            result = QString::fromStdString(ss.str());
            break;
          }
        }

      }
    }
  }
  return (result.isEmpty()) ? QStringLiteral("UNKNOWN") : result;
}

void ScreenshotDialog::cmdTopShotToDir(QString path) {

  WId activeWid = activeWindowId();
  const QRect rect = (activeWid) ? windowFrame(activeWid) : QRect{0, 0, -1, -1};
  QImage img{takeScreenshot(QApplication::desktop()->winId(), rect, false)};

  QDir d;
  d.mkpath(path);
  QFileInfo fi(path);
  if(!fi.exists() || !fi.isDir() || !fi.isWritable()) {
    path = QDir::homePath();
  }
  const QString filename = QStringLiteral("%1/%2_%3").arg(path).arg(getWindowName(activeWid)).arg(buildNumericFnPart());

  const auto static png = QStringLiteral(".png");
  QString finalName = filename % png;

  //most unlikelly this will happen ... but user might change system clock or so and we dont want to overwrite file
  for(int counter = 0; QFile::exists(finalName) && counter < 5000; ++counter) {
    finalName = QStringLiteral("%1_%2%3").arg(filename).arg(counter).arg(png);
  }
  //std::cout << finalName.toStdString() << std::endl;
  img.save(finalName);
}

三、下载链接

https://download.csdn.net/download/u013083044/88628914

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1311316.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JS加密/解密之JSX解密解析(photoshop插件)

简介 Adobe Photoshop 插件通常使用 JSX&#xff08;JavaScript XML&#xff09;脚本语言。这是一种基于JavaScript的扩展&#xff0c;专门设计用于处理Adobe Creative Suite&#xff08;包括Photoshop&#xff09;的任务。JSX脚本允许开发者编写自定义脚本以扩展和增强Photos…

【Eureka】自定义元数据消失原因?

【Eureka】自定义元数据运行很长一段时间后&#xff0c;自定义元数据&#xff08;scheduler.server.enabled&#xff09;偶尔会消失&#xff0c;但服务元数据信息还在 eureka是单节点的&#xff0c;这个应用服务也是单节点的 代码实现方式如下 我看过eureka服务的日志信息&…

在做题中学习(33):只出现一次的数字 II

137. 只出现一次的数字 II - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 1.首先想到出现三次的数&#xff0c;它们仨的任意一位都是相同的&#xff08;1/0&#xff09; 2.可以发现出现三次的数的某一位和a某一位在所有情况下%3最后的结果都和a的那一位相同&…

06.迪米特法则(Demeter Principle)

明 嘉靖四十年 江南织造总局 小黄门唯唯诺诺的听完了镇守太监杨金水的训斥&#xff0c;赶忙回答&#xff1a;“知道了&#xff0c;干爹&#xff01;” “知道什么&#xff1f;&#xff01;&#xff01;” 杨金水打断了他的话&#xff0c;眼神突然变得凌厉起来&#xff1a; “有…

企业计算机服务器中了halo勒索病毒如何解密,halo勒索病毒恢复流程

网络技术的不断发展与应用&#xff0c;为企业的生产运营提供了极大便利&#xff0c;越来越多的企业使用数据库存储企业的重要数据&#xff0c;方便工作与生产&#xff0c;但网络是一把双刃剑&#xff0c;网络安全威胁一直存在&#xff0c;并且网络威胁的手段也在不断升级。在本…

我的隐私计算学习——匿踪查询

笔记内容来自多本书籍、学术资料、白皮书及ChatGPT等工具&#xff0c;经由自己阅读后整理而成。 &#xff08;一&#xff09;PIR的介绍 ​ 匿踪查询&#xff0c;即隐私信息检索&#xff08;Private InformationRetrieval&#xff0c;PIR&#xff09;&#xff0c;是安全多方计算…

C# OpenVINO 直接读取百度模型实现印章检测

目录 效果 模型信息 项目 代码 下载 其他 C# OpenVINO 直接读取百度模型实现印章检测 效果 模型信息 Inputs ------------------------- name&#xff1a;scale_factor tensor&#xff1a;F32[?, 2] name&#xff1a;image tensor&#xff1a;F32[?, 3, 608, 608] …

Windows更改远程桌面端口并添加防火墙入站规则

1.运行 快捷键winR组合键&#xff0c;win就是键盘上的windows系统图标键。 2.打开注册表 Regedit&#xff0c;在对话框中输入regedit命令&#xff0c;然后回车 3.打开注册表&#xff0c;输入命令后&#xff0c;会打开系统的注册表&#xff0c;左边是目录栏&#xff0c;右边是…

基于STM32的智能小区环境监测

一、概述 本系统应用STM32F407VET6单片机为控制处理器&#xff0c;加上外设备组成单片机最小系统。配以输入输出部分&#xff0c;通过采集温湿度、甲醛、PM2.5等数据在LCD液晶上显示&#xff0c;内加单独时钟晶振电路&#xff0c;保护断电后时间参数不变&#xff0c;外接5v电源…

QGIS 加载在线XYZ地图图层

QGIS 加载在线XYZ地图图层 定义并添加必应XYZ图层 Go to Layer > Add Layer > Add XYZ Layer…Click NewName as BingMaps(as you wish)URL as http://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g1click OkSelect XYZ Connections as Bing Maps(Which you creat…

C++之获取变量信息名称、类型typeid

摘要 对于C工程量级比较庞大的代码&#xff0c;代码中的变量、类、函数、结构体的识别都是一件让人头疼的事情&#xff0c;一方面代码越写越多&#xff0c;内容越来越丰富&#xff0c;但是没有办法对已有的代码框架进行高度的整合提炼&#xff1b;另一方面对新人逐渐不友好&am…

python 协程

python 协程 协程为什么需要协程&#xff1f;协程与子线程的区别协程的工作原理协程的优缺点协程优点协程缺点 协程的实现yield 关键字greenlet 模块gevent 模块Pool 限制并发 协程 协程又称微线程&#xff0c;英文名coroutine。协程是用户态的一种轻量级线程&#xff0c;是由…

Visual Studio开发环境的搭建

1.引言 Visual Studio是微软公司开发的一款强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它可以帮助开发人员进行各种编程任务&#xff0c;包括设计、开发、测试、调试和部署应用程序。典型功能包括&#xff1a; 代码编辑器。提供高效、智能的代码编辑器&#x…

一文读懂FastAPI:Python 开发者的福音

FastAPI是一个基于Python的现代化Web框架&#xff0c;它提供了快速、简单和高性能的方式来构建API。 它结合了Python的静态类型检查和自动化文档生成的功能&#xff0c;使得开发API变得更加容易和高效。 下面将介绍如何使用FastAPI快速开发接口&#xff0c;并且利用自动生成的…

Red Hat Satellite - 为主机配置可使用的内容(存储库),注册主机并安装软件包

《OpenShift / RHEL / DevSecOps 汇总目录》 请先根据《Red Hat Satellite - 导入订阅清单》一文完成向 Red Hat Satellite 导入分配的订阅订单。 本文中的相关概念请参见《Red Hat Satellite - 核心概念篇》。 文章目录 配置 Repository 并同步配置生命周期的环境路径配置内容…

死锁的概念

死锁&#xff08;Deadlock&#xff09;、饥饿&#xff08;Starvation&#xff09;和死循环&#xff08;Infinite Loop&#xff09;是计算机科学中与并发和并行处理相关的三个概念&#xff0c;它们描述了不同类型的问题和情况。 死锁&#xff08;Deadlock&#xff09;: 定义: 死…

优先考虑静态成员类

在Java中&#xff0c;静态成员类&#xff08;static nested class&#xff09;是一种嵌套在另一个类中的类&#xff0c;且被声明为静态。静态成员类不依赖于外部类的实例&#xff0c;可以直接通过外部类的类名来访问。 优先考虑使用静态成员类的情况通常是当这个类与外部类的实…

IC卡卡号修改UID卡CUID卡物理卡号修改考勤工号修改

普通M1卡的物理卡号是锁死的&#xff0c;UID卡、CUID卡、FUID卡是特殊的M1卡&#xff0c;他们的物理卡号是可以修改的。考勤卡、门禁等读取到的IC卡卡号是这样的0136098153&#xff0c;10位卡号&#xff0c;这个卡号是随机的&#xff0c;不连续的&#xff0c;没有规律&#xff…

纯干货|聊一聊大促活动背后的技术:火山引擎边缘云CDN/DCDN/GA

12月12日&#xff0c;“抖音商城双12好物节”正式结束。据了解&#xff0c;双12期间&#xff0c;抖音电商推出了超值购、秒杀等多个优价频道和多个类目的主题榜单&#xff0c;让有消费需求的用户更高效地发现高性价比好物。除了货架场景&#xff0c;“抖音商城双12好物节”还发…

基于ssm校园资讯推荐系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园资讯推荐系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…