File indexing completed on 2025-01-05 03:59:44

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2013-07-15
0007  * Description : a widget to draw an image clip region.
0008  *
0009  * SPDX-FileCopyrightText: 2013-2014 by Yiou Wang <geow812 at gmail dot com>
0010  * SPDX-FileCopyrightText: 2010-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0011  * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "imageregionwidget.h"
0018 
0019 // C++ includes
0020 
0021 #include <cmath>
0022 
0023 // Qt includes
0024 
0025 #include <QTimer>
0026 #include <QIcon>
0027 
0028 // KDE includes
0029 
0030 #include <klocalizedstring.h>
0031 
0032 // Local includes
0033 
0034 #include "digikam_debug.h"
0035 #include "imageregionitem.h"
0036 #include "previewtoolbar.h"
0037 #include "previewlayout.h"
0038 #include "dimgitems_p.h"
0039 
0040 namespace Digikam
0041 {
0042 
0043 class Q_DECL_HIDDEN ImageRegionWidget::Private
0044 {
0045 
0046 public:
0047 
0048     explicit Private()
0049       : capturePtMode(false),
0050         renderingPreviewMode(PreviewToolBar::PreviewBothImagesVertCont),
0051         oldRenderingPreviewMode(PreviewToolBar::PreviewBothImagesVertCont),
0052         delay(nullptr),
0053         item(nullptr)
0054     {
0055     }
0056 
0057     DImg             targetImage;
0058 
0059     bool             capturePtMode;
0060 
0061     int              renderingPreviewMode;
0062     int              oldRenderingPreviewMode;
0063 
0064     QPolygon         hightlightPoints;
0065 
0066     QTimer*          delay;
0067 
0068     ImageRegionItem* item;
0069 };
0070 
0071 ImageRegionWidget::ImageRegionWidget(QWidget* const parent, bool paintExtras)
0072     : GraphicsDImgView(parent),
0073       d_ptr(new Private)
0074 {
0075     d_ptr->item = new ImageRegionItem(this, paintExtras);
0076     setItem(d_ptr->item);
0077 
0078     setAttribute(Qt::WA_DeleteOnClose);
0079     setFrameStyle(QFrame::NoFrame);
0080     setMinimumSize(480, 320);
0081     setWhatsThis(i18n("<p>Here you can see the original clip image "
0082                       "which will be used for the preview computation.</p>"
0083                       "<p>Click and drag the mouse cursor in the "
0084                       "image to change the clip focus.</p>"));
0085 
0086     d_ptr->delay = new QTimer(this);
0087     d_ptr->delay->setInterval(500);
0088     d_ptr->delay->setSingleShot(true);
0089 
0090     connect(d_ptr->delay, SIGNAL(timeout()),
0091             this, SLOT(slotOriginalImageRegionChanged()));
0092 
0093     connect(this, SIGNAL(viewportRectChanged(QRectF)),
0094             this, SLOT(slotOriginalImageRegionChangedDelayed()));
0095 
0096     layout()->fitToWindow();
0097     installPanIcon();
0098 }
0099 
0100 ImageRegionWidget::~ImageRegionWidget()
0101 {
0102     delete d_ptr->item;
0103     delete d_ptr;
0104 }
0105 
0106 void ImageRegionWidget::setHighLightPoints(const QPolygon& pointsList)
0107 {
0108     d_ptr->item->setHighLightPoints(pointsList);
0109     viewport()->update();
0110 }
0111 
0112 void ImageRegionWidget::setCapturePointMode(bool b)
0113 {
0114     if (d_ptr->capturePtMode && b)
0115     {
0116         return;
0117     }
0118 
0119     d_ptr->capturePtMode = b;
0120     viewport()->setMouseTracking(!b);
0121 
0122     if (b)
0123     {
0124         d_ptr->oldRenderingPreviewMode = d_ptr->renderingPreviewMode;
0125         slotPreviewModeChanged(PreviewToolBar::PreviewOriginalImage);
0126         viewport()->setCursor(QCursor(QIcon::fromTheme(QLatin1String("color-picker")).pixmap(32), 4, 27));
0127     }
0128     else
0129     {
0130         slotPreviewModeChanged(d_ptr->oldRenderingPreviewMode);
0131         viewport()->unsetCursor();
0132     }
0133 }
0134 
0135 void ImageRegionWidget::slotPreviewModeChanged(int mode)
0136 {
0137     d_ptr->renderingPreviewMode = mode;
0138     d_ptr->item->setRenderingPreviewMode(mode);
0139     slotOriginalImageRegionChanged();
0140     viewport()->update();
0141 }
0142 
0143 QRect ImageRegionWidget::getOriginalImageRegionToRender() const
0144 {
0145     QRect  r = d_ptr->item->getImageRegion();
0146     double z = layout()->realZoomFactor();
0147 
0148     int x    = qRound((double)r.x()      / z);
0149     int y    = qRound((double)r.y()      / z);
0150     int w    = qRound((double)r.width()  / z);
0151     int h    = qRound((double)r.height() / z);
0152 
0153     QRect rect(x, y, w, h);
0154     return (rect);
0155 }
0156 
0157 void ImageRegionWidget::setPreviewImage(const DImg& img)
0158 {
0159     d_ptr->targetImage = img;
0160     QRect r            = d_ptr->item->getImageRegion();
0161     d_ptr->targetImage.resize(r.width(), r.height());
0162 
0163     // Because tool which only work on image data, the DImg container
0164     // do not contain metadata from original image. About Color Managed View, we need to
0165     // restore the embedded ICC color profile.
0166     // However, some tools may set a profile on the preview image, which we accept of course.
0167 
0168     if (d_ptr->targetImage.getIccProfile().isNull())
0169     {
0170         d_ptr->targetImage.setIccProfile(d_ptr->item->image().getIccProfile());
0171     }
0172 
0173     d_ptr->item->setTargetImage(d_ptr->targetImage);
0174 }
0175 
0176 DImg ImageRegionWidget::getOriginalImage() const
0177 {
0178     return (d_ptr->item->image().copy());
0179 }
0180 
0181 DImg ImageRegionWidget::getOriginalRegionImage(bool useDownscaledImage) const
0182 {
0183     DImg image = d_ptr->item->image().copy(getOriginalImageRegionToRender());
0184 
0185     if (useDownscaledImage)
0186     {
0187         QRect r = d_ptr->item->getImageRegion();
0188         image.resize(r.width(), r.height());
0189     }
0190 
0191     return (image);
0192 }
0193 
0194 void ImageRegionWidget::slotOriginalImageRegionChangedDelayed()
0195 {
0196     viewport()->update();
0197     d_ptr->delay->start();
0198 }
0199 
0200 void ImageRegionWidget::slotOriginalImageRegionChanged(bool targetDone)
0201 {
0202     if (targetDone)
0203     {
0204         Q_EMIT signalOriginalClipFocusChanged(); // For Image Edit Tools
0205     }
0206 }
0207 
0208 void ImageRegionWidget::exposureSettingsChanged()
0209 {
0210     d_ptr->item->clearCache();
0211     d_ptr->item->setTargetImage(d_ptr->targetImage);
0212 }
0213 
0214 void ImageRegionWidget::ICCSettingsChanged()
0215 {
0216     d_ptr->item->clearCache();
0217     d_ptr->item->setTargetImage(d_ptr->targetImage);
0218 }
0219 
0220 void ImageRegionWidget::mousePressEvent(QMouseEvent* e)
0221 {
0222     if (d_ptr->capturePtMode)
0223     {
0224         emitCapturedPointFromOriginal(mapToScene(e->pos()));
0225         QGraphicsView::mousePressEvent(e);
0226         return;
0227     }
0228 
0229     GraphicsDImgView::mousePressEvent(e);
0230 }
0231 
0232 void ImageRegionWidget::mouseReleaseEvent(QMouseEvent* e)
0233 {
0234     if (d_ptr->capturePtMode)
0235     {
0236         setCapturePointMode(false);
0237         QGraphicsView::mouseReleaseEvent(e);
0238         return;
0239     }
0240 
0241     GraphicsDImgView::mouseReleaseEvent(e);
0242 }
0243 
0244 void ImageRegionWidget::emitCapturedPointFromOriginal(const QPointF& pt)
0245 {
0246     int x        = (int)(pt.x() / layout()->realZoomFactor());
0247     int y        = (int)(pt.y() / layout()->realZoomFactor());
0248     QPoint imgPt(x, y);
0249     DColor color = d_ptr->item->image().getPixelColor(x, y);
0250     qCDebug(DIGIKAM_GENERAL_LOG) << "Captured point from image : " << imgPt;
0251     Q_EMIT signalCapturedPointFromOriginal(color, imgPt);
0252 }
0253 
0254 void ImageRegionWidget::updateImage(const DImg& img)
0255 {
0256     d_ptr->item->setImage(img);
0257 }
0258 
0259 } // namespace Digikam
0260 
0261 #include "moc_imageregionwidget.cpp"