libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

viewer_window.cc (4017B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #include "tools/viewer/viewer_window.h"
      7 
      8 #include <QElapsedTimer>
      9 #include <QFileDialog>
     10 #include <QFileInfo>
     11 #include <QKeyEvent>
     12 #include <QMessageBox>
     13 #include <QSet>
     14 
     15 #include "tools/icc_detect/icc_detect.h"
     16 #include "tools/viewer/load_jxl.h"
     17 
     18 namespace jpegxl {
     19 namespace tools {
     20 
     21 namespace {
     22 
     23 template <typename Output>
     24 void recursivelyAddSubEntries(const QFileInfo& info,
     25                               QSet<QString>* const visited,
     26                               Output* const output) {
     27   if (visited->contains(info.absoluteFilePath())) return;
     28   *visited << info.absoluteFilePath();
     29   if (info.isDir()) {
     30     QDir dir(info.absoluteFilePath());
     31     for (const QFileInfo& entry : dir.entryInfoList(
     32              QStringList() << "*.jxl",
     33              QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot)) {
     34       recursivelyAddSubEntries(entry, visited, output);
     35     }
     36   } else {
     37     *output << info.absoluteFilePath();
     38   }
     39 }
     40 
     41 }  // namespace
     42 
     43 ViewerWindow::ViewerWindow(QWidget* const parent)
     44     : QMainWindow(parent), monitorProfile_(GetMonitorIccProfile(this)) {
     45   ui_.setupUi(this);
     46   ui_.actionOpen->setShortcut(QKeySequence::Open);
     47   ui_.actionExit->setShortcut(QKeySequence::Quit);
     48 }
     49 
     50 void ViewerWindow::loadFilesAndDirectories(QStringList entries) {
     51   filenames_.clear();
     52   QSet<QString> visited;
     53   for (const QString& entry : entries) {
     54     recursivelyAddSubEntries(QFileInfo(entry), &visited, &filenames_);
     55   }
     56 
     57   const bool several = filenames_.size() > 1;
     58   ui_.actionPreviousImage->setEnabled(several);
     59   ui_.actionNextImage->setEnabled(several);
     60 
     61   currentFileIndex_ = 0;
     62   refreshImage();
     63 }
     64 
     65 void ViewerWindow::on_actionOpen_triggered() {
     66   QFileDialog dialog(this, tr("Select JPEG XL files to open…"));
     67   dialog.setFileMode(QFileDialog::ExistingFiles);
     68   dialog.setNameFilter(tr("JPEG XL images (*.jxl);;All files (*)"));
     69   if (dialog.exec()) {
     70     loadFilesAndDirectories(dialog.selectedFiles());
     71   }
     72 }
     73 
     74 void ViewerWindow::on_actionPreviousImage_triggered() {
     75   currentFileIndex_ =
     76       (currentFileIndex_ - 1 + filenames_.size()) % filenames_.size();
     77   refreshImage();
     78 }
     79 
     80 void ViewerWindow::on_actionNextImage_triggered() {
     81   currentFileIndex_ = (currentFileIndex_ + 1) % filenames_.size();
     82   refreshImage();
     83 }
     84 
     85 void ViewerWindow::refreshImage() {
     86   if (currentFileIndex_ < 0 || currentFileIndex_ >= filenames_.size()) {
     87     return;
     88   }
     89 
     90   qint64 elapsed_ns;
     91   bool usedRequestedProfile;
     92   const QImage image =
     93       loadJxlImage(filenames_[currentFileIndex_], monitorProfile_, &elapsed_ns,
     94                    &usedRequestedProfile);
     95   if (image.isNull()) {
     96     const QString message =
     97         tr("Failed to load \"%1\".").arg(filenames_[currentFileIndex_]);
     98     ui_.image->clear();
     99     ui_.statusBar->showMessage(message);
    100     QMessageBox errorDialog(this);
    101     errorDialog.setIcon(QMessageBox::Critical);
    102     errorDialog.setWindowTitle(tr("Failed to load image"));
    103     errorDialog.setText(message);
    104     errorDialog.exec();
    105     return;
    106   }
    107 
    108   ui_.image->setPixmap(QPixmap::fromImage(image));
    109   ui_.statusBar->showMessage(
    110       tr("Loaded image %L1/%L2 (%3, %4×%5) in %L6ms (%L7 fps)")
    111           .arg(currentFileIndex_ + 1)
    112           .arg(filenames_.size())
    113           .arg(filenames_[currentFileIndex_])
    114           .arg(image.width())
    115           .arg(image.height())
    116           .arg(elapsed_ns / 1e6)
    117           .arg(1e9 / elapsed_ns));
    118 
    119   if (!usedRequestedProfile && !hasWarnedAboutMonitorProfile_) {
    120     hasWarnedAboutMonitorProfile_ = true;
    121     QMessageBox message(this);
    122     message.setIcon(QMessageBox::Warning);
    123     message.setWindowTitle(tr("No valid monitor profile found"));
    124     message.setText(
    125         tr("Failed to find a usable monitor profile. Images will be shown "
    126            "assuming that the monitor's colorspace is sRGB."));
    127     message.exec();
    128   }
    129 }
    130 
    131 }  // namespace tools
    132 }  // namespace jpegxl