libjxl

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

split_view.cc (5669B)


      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/flicker_test/split_view.h"
      7 
      8 #include <QMouseEvent>
      9 #include <QPainter>
     10 
     11 namespace jpegxl {
     12 namespace tools {
     13 
     14 SplitView::SplitView(QWidget* const parent)
     15     : QWidget(parent), g_(std::random_device()()) {
     16   blankingTimer_.setSingleShot(true);
     17   blankingTimer_.setTimerType(Qt::PreciseTimer);
     18   viewingTimer_.setSingleShot(true);
     19   viewingTimer_.setTimerType(Qt::PreciseTimer);
     20   flicker_.setLoopCount(-1);
     21   connect(&blankingTimer_, &QTimer::timeout, this, &SplitView::startDisplaying);
     22   connect(&flicker_, &QVariantAnimation::valueChanged, this, [&] {
     23     if (gray_) {
     24       update();
     25     }
     26   });
     27   connect(&flicker_, &QAbstractAnimation::currentLoopChanged, [&] {
     28     showingAltered_ = !showingAltered_;
     29     update();
     30   });
     31   connect(&viewingTimer_, &QTimer::timeout, [&] {
     32     flicker_.stop();
     33     original_.fill(Qt::black);
     34     altered_.fill(Qt::black);
     35     update();
     36   });
     37 }
     38 
     39 void SplitView::setOriginalImage(QImage image) {
     40   original_ = QPixmap::fromImage(std::move(image));
     41   original_.setDevicePixelRatio(devicePixelRatio());
     42   updateMinimumSize();
     43   update();
     44 }
     45 
     46 void SplitView::setAlteredImage(QImage image) {
     47   altered_ = QPixmap::fromImage(std::move(image));
     48   altered_.setDevicePixelRatio(devicePixelRatio());
     49   updateMinimumSize();
     50   update();
     51 }
     52 
     53 void SplitView::setSpacing(int spacing) {
     54   spacing_ = spacing;
     55   updateMinimumSize();
     56   update();
     57 }
     58 
     59 void SplitView::startTest(QString imageName, const int blankingTimeMSecs,
     60                           const int viewingTimeSecs, const int advanceTimeMSecs,
     61                           const bool gray, const int grayFadingTimeMSecs,
     62                           const int grayTimeMSecs) {
     63   imageName_ = std::move(imageName);
     64   std::bernoulli_distribution bernoulli;
     65   originalSide_ = bernoulli(g_) ? Side::kLeft : Side::kRight;
     66   viewingTimer_.setInterval(1000 * viewingTimeSecs);
     67 
     68   flicker_.setDuration(advanceTimeMSecs);
     69   gray_ = gray;
     70   QVariantAnimation::KeyValues keyValues;
     71   if (gray_) {
     72     keyValues << QVariantAnimation::KeyValue(0., 0.f)
     73               << QVariantAnimation::KeyValue(
     74                      static_cast<float>(grayFadingTimeMSecs) / advanceTimeMSecs,
     75                      1.f)
     76               << QVariantAnimation::KeyValue(
     77                      static_cast<float>(advanceTimeMSecs - grayTimeMSecs -
     78                                         grayFadingTimeMSecs) /
     79                          advanceTimeMSecs,
     80                      1.f)
     81               << QVariantAnimation::KeyValue(
     82                      static_cast<float>(advanceTimeMSecs - grayTimeMSecs) /
     83                          advanceTimeMSecs,
     84                      0.f)
     85               << QVariantAnimation::KeyValue(1.f, 0.f);
     86   } else {
     87     keyValues << QVariantAnimation::KeyValue(0., 1.f)
     88               << QVariantAnimation::KeyValue(1., 1.f);
     89   }
     90   flicker_.setKeyValues(keyValues);
     91 
     92   state_ = State::kBlanking;
     93   blankingTimer_.start(blankingTimeMSecs);
     94 }
     95 
     96 void SplitView::mousePressEvent(QMouseEvent* const event) {
     97   if (state_ != State::kDisplaying) return;
     98 
     99   if (leftRect_.contains(event->pos())) {
    100     clicking_ = true;
    101     clickedSide_ = Side::kLeft;
    102   } else if (rightRect_.contains(event->pos())) {
    103     clicking_ = true;
    104     clickedSide_ = Side::kRight;
    105   }
    106 }
    107 
    108 void SplitView::mouseReleaseEvent(QMouseEvent* const event) {
    109   if (!clicking_) return;
    110   clicking_ = false;
    111 
    112   const int clickDelayMSecs = viewingStartTime_.elapsed();
    113 
    114   if ((clickedSide_ == Side::kLeft && !leftRect_.contains(event->pos())) ||
    115       (clickedSide_ == Side::kRight && !rightRect_.contains(event->pos()))) {
    116     return;
    117   }
    118 
    119   flicker_.stop();
    120   viewingTimer_.stop();
    121   state_ = State::kBlanking;
    122   update();
    123 
    124   emit testResult(imageName_, originalSide_, clickedSide_, clickDelayMSecs);
    125 }
    126 
    127 void SplitView::paintEvent(QPaintEvent* const event) {
    128   QPainter painter(this);
    129   painter.fillRect(rect(), QColor(119, 119, 119));
    130 
    131   if (state_ == State::kBlanking) return;
    132 
    133   if (gray_ && flicker_.state() == QAbstractAnimation::Running) {
    134     painter.setOpacity(flicker_.currentValue().toFloat());
    135   }
    136 
    137   const auto imageForSide = [&](const Side side) {
    138     if (side == originalSide_) return &original_;
    139     return showingAltered_ ? &altered_ : &original_;
    140   };
    141 
    142   QPixmap* const leftImage = imageForSide(Side::kLeft);
    143   QPixmap* const rightImage = imageForSide(Side::kRight);
    144 
    145   leftRect_ = QRectF(QPoint(), leftImage->deviceIndependentSize());
    146   leftRect_.moveCenter(rect().center());
    147   leftRect_.moveRight(rect().center().x() -
    148                       (spacing_ / 2 + spacing_ % 2) / devicePixelRatio());
    149   painter.drawPixmap(leftRect_.topLeft(), *leftImage);
    150 
    151   rightRect_ = QRectF(QPoint(), rightImage->deviceIndependentSize());
    152   rightRect_.moveCenter(rect().center());
    153   rightRect_.moveLeft(rect().center().x() +
    154                       (spacing_ / 2) / devicePixelRatio());
    155   painter.drawPixmap(rightRect_.topLeft(), *rightImage);
    156 }
    157 
    158 void SplitView::startDisplaying() {
    159   state_ = State::kDisplaying;
    160   flicker_.start();
    161   viewingStartTime_.start();
    162   if (viewingTimer_.interval() > 0) {
    163     viewingTimer_.start();
    164   }
    165 }
    166 
    167 void SplitView::updateMinimumSize() {
    168   setMinimumWidth(2 * std::max(original_.deviceIndependentSize().width(),
    169                                altered_.deviceIndependentSize().width()) +
    170                   spacing_ / devicePixelRatio());
    171   setMinimumHeight(std::max(original_.deviceIndependentSize().height(),
    172                             altered_.deviceIndependentSize().height()));
    173 }
    174 
    175 }  // namespace tools
    176 }  // namespace jpegxl