File indexing completed on 2025-01-19 03:59:17
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2013-07-25 0007 * Description : image region widget item for image editor. 0008 * 0009 * SPDX-FileCopyrightText: 2013-2014 by Yiou Wang <geow812 at gmail dot com> 0010 * SPDX-FileCopyrightText: 2013-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "imageregionitem.h" 0017 0018 // Qt includes 0019 0020 #include <QPixmap> 0021 #include <QPainter> 0022 0023 // KDE includes 0024 0025 #include <klocalizedstring.h> 0026 0027 // Local includes 0028 0029 #include "digikam_debug.h" 0030 #include "dimgitems_p.h" 0031 #include "editorcore.h" 0032 #include "exposurecontainer.h" 0033 #include "iccmanager.h" 0034 #include "icctransform.h" 0035 #include "iccsettingscontainer.h" 0036 #include "imageiface.h" 0037 #include "previewtoolbar.h" 0038 0039 namespace Digikam 0040 { 0041 0042 class Q_DECL_HIDDEN ImageRegionItem::Private 0043 { 0044 public: 0045 0046 explicit Private() 0047 : paintExtras (true), 0048 onMouseMovePreviewToggled(true), 0049 renderingPreviewMode (PreviewToolBar::PreviewBothImagesVertCont), 0050 view (nullptr), 0051 iface (nullptr) 0052 { 0053 } 0054 0055 bool paintExtras; 0056 bool onMouseMovePreviewToggled; 0057 int renderingPreviewMode; 0058 0059 QPixmap targetPix; ///< Pixmap of target region to render for paint method. 0060 QRect drawRect; 0061 QPolygon hightlightPoints; 0062 0063 ImageRegionWidget* view; 0064 ImageIface* iface; 0065 }; 0066 0067 ImageRegionItem::ImageRegionItem(ImageRegionWidget* const widget, bool paintExtras) 0068 : dd(new Private) 0069 { 0070 dd->view = widget; 0071 dd->iface = new ImageIface; 0072 dd->paintExtras = paintExtras; 0073 0074 setDisplayWidget(widget); 0075 setAcceptHoverEvents(true); 0076 setImage(dd->iface->original() ? dd->iface->original()->copy() : DImg()); 0077 } 0078 0079 ImageRegionItem::~ImageRegionItem() 0080 { 0081 delete dd->iface; 0082 delete dd; 0083 } 0084 0085 QRect ImageRegionItem::getImageRegion() const 0086 { 0087 return dd->drawRect; 0088 } 0089 0090 void ImageRegionItem::setTargetImage(const DImg& img) 0091 { 0092 dd->targetPix = dd->iface->convertToPixmap(img); 0093 update(); 0094 } 0095 0096 void ImageRegionItem::setRenderingPreviewMode(int mode) 0097 { 0098 dd->renderingPreviewMode = mode; 0099 update(); 0100 } 0101 0102 void ImageRegionItem::setHighLightPoints(const QPolygon& pointsList) 0103 { 0104 dd->hightlightPoints = pointsList; 0105 } 0106 0107 void ImageRegionItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) 0108 { 0109 Q_D(GraphicsDImgItem); 0110 0111 dd->drawRect = option->exposedRect.intersected(boundingRect()).toAlignedRect(); 0112 QRect pixSourceRect; 0113 QPixmap pix; 0114 QSize completeSize = boundingRect().size().toSize(); 0115 0116 // scale "as if" scaling to whole image, but clip output to our exposed region 0117 0118 DImg scaledImage = d->image.smoothScaleClipped(completeSize.width(), 0119 completeSize.height(), 0120 dd->drawRect.x(), 0121 dd->drawRect.y(), 0122 dd->drawRect.width(), 0123 dd->drawRect.height()); 0124 0125 if (d->cachedPixmaps.find(dd->drawRect, &pix, &pixSourceRect)) 0126 { 0127 if (pixSourceRect.isNull()) 0128 { 0129 painter->drawPixmap(dd->drawRect.topLeft(), pix); 0130 } 0131 else 0132 { 0133 painter->drawPixmap(dd->drawRect.topLeft(), pix, pixSourceRect); 0134 } 0135 } 0136 else 0137 { 0138 // TODO: factoring ICC settings code using ImageIface/EditorCore methods. 0139 0140 // Apply CM settings. 0141 0142 bool doSoftProofing = EditorCore::defaultInstance()->softProofingEnabled(); 0143 ICCSettingsContainer iccSettings = EditorCore::defaultInstance()->getICCSettings(); 0144 0145 if (iccSettings.enableCM && (iccSettings.useManagedView || doSoftProofing)) 0146 { 0147 IccManager manager(scaledImage); 0148 IccTransform monitorICCtrans; 0149 0150 if (doSoftProofing) 0151 { 0152 monitorICCtrans = manager.displaySoftProofingTransform(IccProfile(iccSettings.defaultProofProfile), widget); 0153 } 0154 else 0155 { 0156 monitorICCtrans = manager.displayTransform(widget); 0157 } 0158 0159 pix = scaledImage.convertToPixmap(monitorICCtrans); 0160 } 0161 else 0162 { 0163 pix = scaledImage.convertToPixmap(); 0164 } 0165 0166 d->cachedPixmaps.insert(dd->drawRect, pix); 0167 0168 painter->drawPixmap(dd->drawRect.topLeft(), pix); 0169 } 0170 0171 if (dd->paintExtras) 0172 { 0173 paintExtraData(painter); 0174 } 0175 0176 // Show the Over/Under exposure pixels indicators 0177 0178 ExposureSettingsContainer* const expoSettings = EditorCore::defaultInstance()->getExposureSettings(); 0179 0180 if (expoSettings) 0181 { 0182 if (expoSettings->underExposureIndicator || expoSettings->overExposureIndicator) 0183 { 0184 QImage pureColorMask = scaledImage.pureColorMask(expoSettings); 0185 QPixmap pixMask = QPixmap::fromImage(pureColorMask); 0186 painter->drawPixmap(dd->drawRect.topLeft(), pixMask); 0187 } 0188 } 0189 } 0190 0191 void ImageRegionItem::paintExtraData(QPainter* const p) 0192 { 0193 QRect viewportRect = boundingRect().toAlignedRect(); 0194 QRect fontRectBefore = p->fontMetrics().boundingRect(viewportRect, 0, i18n("Before")); 0195 QRect fontRectAfter = p->fontMetrics().boundingRect(viewportRect, 0, i18n("After")); 0196 0197 p->setRenderHint(QPainter::Antialiasing, true); 0198 p->setBackgroundMode(Qt::TransparentMode); 0199 0200 if ((dd->renderingPreviewMode == PreviewToolBar::PreviewOriginalImage) || 0201 ((dd->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver) && !dd->onMouseMovePreviewToggled)) 0202 { 0203 dd->view->drawText(p, QRectF(QPointF(dd->drawRect.topLeft().x() + 20, 0204 dd->drawRect.topLeft().y() + 20), 0205 fontRectBefore.size()), i18n("Before")); 0206 } 0207 0208 else if ((dd->renderingPreviewMode == PreviewToolBar::PreviewTargetImage) || 0209 (dd->renderingPreviewMode == PreviewToolBar::NoPreviewMode) || 0210 ((dd->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver) && dd->onMouseMovePreviewToggled)) 0211 { 0212 p->drawPixmap(dd->drawRect.x(), dd->drawRect.y(), dd->targetPix, 0213 0, 0, dd->drawRect.width(), dd->drawRect.height()); 0214 0215 if ((dd->renderingPreviewMode == PreviewToolBar::PreviewTargetImage) || 0216 (dd->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver)) 0217 { 0218 dd->view->drawText(p, QRectF(QPointF(dd->drawRect.topLeft().x() + 20, 0219 dd->drawRect.topLeft().y() + 20), 0220 fontRectAfter.size()), i18n("After")); 0221 } 0222 } 0223 0224 else if ((dd->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert) || 0225 (dd->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVertCont)) 0226 { 0227 if (dd->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert) 0228 { 0229 p->drawPixmap(dd->drawRect.x() + dd->drawRect.width() / 2, dd->drawRect.y(), 0230 dd->targetPix, 0, 0, dd->drawRect.width()/2, dd->drawRect.height()); 0231 } 0232 0233 if (dd->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVertCont) 0234 { 0235 p->drawPixmap(dd->drawRect.x() + dd->drawRect.width() / 2, dd->drawRect.y(), 0236 dd->targetPix, dd->drawRect.width()/2, 0, dd->drawRect.width(), dd->drawRect.height()); 0237 } 0238 0239 p->setPen(QPen(Qt::white, 2, Qt::SolidLine)); 0240 p->drawLine(dd->drawRect.topLeft().x() + dd->drawRect.width()/2, dd->drawRect.topLeft().y(), 0241 dd->drawRect.topLeft().x() + dd->drawRect.width()/2, dd->drawRect.bottomLeft().y()); 0242 p->setPen(QPen(Qt::red, 2, Qt::DotLine)); 0243 p->drawLine(dd->drawRect.topLeft().x() + dd->drawRect.width()/2, dd->drawRect.topLeft().y(), 0244 dd->drawRect.topLeft().x() + dd->drawRect.width()/2, dd->drawRect.bottomLeft().y()); 0245 dd->view->drawText(p, QRectF(QPointF(dd->drawRect.topLeft().x() + 20, 0246 dd->drawRect.topLeft().y() + 20), 0247 fontRectBefore.size()), i18n("Before")); 0248 dd->view->drawText(p, QRectF(QPointF(dd->drawRect.topLeft().x() + dd->drawRect.width()/2 + 20, 0249 dd->drawRect.topLeft().y() + 20), 0250 fontRectAfter.size()), i18n("After")); 0251 } 0252 0253 else if ((dd->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz) || 0254 (dd->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorzCont)) 0255 { 0256 if (dd->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz) 0257 { 0258 p->drawPixmap(dd->drawRect.x(), dd->drawRect.y() + dd->drawRect.height() / 2, 0259 dd->targetPix, 0, 0, dd->drawRect.width(), dd->drawRect.height()/2); 0260 } 0261 0262 if (dd->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorzCont) 0263 { 0264 p->drawPixmap(dd->drawRect.x(), dd->drawRect.y() + dd->drawRect.height() / 2, 0265 dd->targetPix, 0, dd->drawRect.height()/2, dd->drawRect.width(), dd->drawRect.height()); 0266 } 0267 0268 p->setPen(QPen(Qt::white, 2, Qt::SolidLine)); 0269 p->drawLine(dd->drawRect.topLeft().x() + 1, dd->drawRect.topLeft().y() + dd->drawRect.height()/2, 0270 dd->drawRect.topRight().x() - 1, dd->drawRect.topLeft().y() + dd->drawRect.height()/2); 0271 p->setPen(QPen(Qt::red, 2, Qt::DotLine)); 0272 p->drawLine(dd->drawRect.topLeft().x() + 1, dd->drawRect.topLeft().y() + dd->drawRect.height()/2, 0273 dd->drawRect.topRight().x() - 1, dd->drawRect.topLeft().y() + dd->drawRect.height()/2); 0274 0275 dd->view->drawText(p, QRectF(QPointF(dd->drawRect.topLeft().x() + 20, 0276 dd->drawRect.topLeft().y() + 20), 0277 fontRectBefore.size()), i18n("Before")); 0278 dd->view->drawText(p, QRectF(QPointF(dd->drawRect.topLeft().x() + 20, 0279 dd->drawRect.topLeft().y() + dd->drawRect.height()/2 + 20), 0280 fontRectAfter.size()), i18n("After")); 0281 } 0282 0283 // Drawing highlighted points. 0284 0285 if (!dd->hightlightPoints.isEmpty()) 0286 { 0287 QPoint pt; 0288 QRectF hpArea; 0289 0290 0291 for (int i = 0 ; i < dd->hightlightPoints.count() ; ++i) 0292 { 0293 pt = dd->hightlightPoints.point(i); 0294 double zoomFactor = zoomSettings()->realZoomFactor(); 0295 int x = (int)((double)pt.x() * zoomFactor); 0296 int y = (int)((double)pt.y() * zoomFactor); 0297 0298 // Check if zoomed point is inside, not actual point 0299 0300 if (dd->drawRect.contains(QPoint(x,y))) 0301 { 0302 /* 0303 QPoint hp(contentsToViewport(QPointF(x, y))); 0304 */ 0305 QPointF hp(mapToScene(QPointF(x, y))); 0306 0307 hpArea.setSize(QSize((int)(16 * zoomFactor), (int)(16 * zoomFactor))); 0308 hpArea.moveCenter(hp); 0309 0310 p->setPen(QPen(Qt::white, 2, Qt::SolidLine)); 0311 p->drawLine(hp.x(), hpArea.y(), hp.x(), hp.y() - (int)(3 * zoomFactor)); 0312 p->drawLine(hp.x(), hp.y() + (int)(3 * zoomFactor), hp.x(), hpArea.bottom()); 0313 p->drawLine(hpArea.x(), hp.y(), hp.x() - (int)(3 * zoomFactor), hp.y()); 0314 p->drawLine(hp.x() + (int)(3 * zoomFactor), hp.y(), hpArea.right(), hp.y()); 0315 0316 p->setPen(QPen(Qt::red, 2, Qt::DotLine)); 0317 p->drawLine(hp.x(), hpArea.y(), hp.x(), hp.y() - (int)(3 * zoomFactor)); 0318 p->drawLine(hp.x(), hp.y() + (int)(3 * zoomFactor), hp.x(), hpArea.bottom()); 0319 p->drawLine(hpArea.x(), hp.y(), hp.x() - (int)(3 * zoomFactor), hp.y()); 0320 p->drawLine(hp.x() + (int)(3 * zoomFactor), hp.y(), hpArea.right(), hp.y()); 0321 } 0322 } 0323 } 0324 } 0325 0326 void ImageRegionItem::hoverEnterEvent(QGraphicsSceneHoverEvent*) 0327 { 0328 dd->onMouseMovePreviewToggled = false; 0329 update(); 0330 } 0331 0332 void ImageRegionItem::hoverLeaveEvent(QGraphicsSceneHoverEvent*) 0333 { 0334 dd->onMouseMovePreviewToggled = true; 0335 update(); 0336 } 0337 0338 } // namespace Digikam 0339 0340 #include "moc_imageregionitem.cpp"