QT- QT-lximagerEidtor图片编辑器

QT- QT-lximagerEidtor图片编辑器

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

一、演示效果

二、关键程序

c 复制代码
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

相关推荐
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner1 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz6 天前
QML Hello World 入门示例
qt
xcyxiner9 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner10 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00613 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术13 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript