1
/* ============================================================
3
* This file is a part of digiKam project
4
* http://www.digikam.org
7
* Description : a widget to draw an image clip region.
9
* Copyright (C) 2004-2012 by Gilles Caulier <caulier dot gilles at gmail dot com>
11
* This program is free software; you can redistribute it
12
* and/or modify it under the terms of the GNU General
13
* Public License as published by the Free Software Foundation;
14
* either version 2, or (at your option)
17
* This program is distributed in the hope that it will be useful,
18
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
* GNU General Public License for more details.
22
* ============================================================ */
24
#include "imageregionwidget.moc"
38
#include <QFontMetrics>
42
#include <kiconloader.h>
49
#include "imageiface.h"
50
#include "previewtoolbar.h"
55
class ImageRegionWidget::Private
61
onMouseMovePreviewToggled(true),
63
renderingPreviewMode(PreviewToolBar::PreviewBothImagesVertCont),
64
oldRenderingPreviewMode(PreviewToolBar::PreviewBothImagesVertCont),
71
bool onMouseMovePreviewToggled;
74
int renderingPreviewMode;
75
int oldRenderingPreviewMode;
79
QPixmap pixmapRegion; // Pixmap of current region to render.
81
QPolygon hightlightPoints;
83
DImg image; // Entire content image to render pixmap.
88
ImageRegionWidget::ImageRegionWidget(QWidget* const parent)
89
: PreviewWidget(parent), d(new Private)
91
d->iface = new ImageIface;
92
d->image = d->iface->original()->copy();
94
setAttribute(Qt::WA_DeleteOnClose);
95
setFrameStyle(QFrame::NoFrame);
96
setMinimumSize(480, 320);
97
setWhatsThis(i18n("<p>Here you can see the original clip image "
98
"which will be used for the preview computation.</p>"
99
"<p>Click and drag the mouse cursor in the "
100
"image to change the clip focus.</p>"));
102
connect(this, SIGNAL(signalZoomFactorChanged(double)),
103
this, SLOT(slotZoomFactorChanged()));
105
connect(this, SIGNAL(signalContentTakeFocus()),
106
this, SLOT(slotContentTakeFocus()));
108
connect(this, SIGNAL(signalContentsMovedEvent(bool)),
109
this, SLOT(slotOriginalImageRegionChanged(bool)));
112
ImageRegionWidget::~ImageRegionWidget()
118
int ImageRegionWidget::previewWidth() const
120
return d->image.width();
123
int ImageRegionWidget::previewHeight() const
125
return d->image.height();
128
bool ImageRegionWidget::previewIsNull() const
130
return d->image.isNull();
133
void ImageRegionWidget::resetPreview()
138
void ImageRegionWidget::paintPreview(QPixmap* const pix, int sx, int sy, int sw, int sh)
140
DImg img = d->image.smoothScaleSection(sx, sy, sw, sh, tileSize(), tileSize());
141
QPixmap pix2 = d->iface->convertToPixmap(img);
143
p.drawPixmap(0, 0, pix2, 0, 0, pix2.width(), pix2.height());
147
void ImageRegionWidget::setHighLightPoints(const QPolygon& pointsList)
149
d->hightlightPoints = pointsList;
150
repaintContents(false);
153
void ImageRegionWidget::setCapturePointMode(bool b)
155
d->capturePtMode = b;
156
viewport()->setMouseTracking(b);
160
d->oldRenderingPreviewMode = d->renderingPreviewMode;
161
slotPreviewModeChanged(PreviewToolBar::PreviewOriginalImage);
162
viewport()->setCursor(QCursor(SmallIcon("color-picker", 32), 1, 28));
166
slotPreviewModeChanged(d->oldRenderingPreviewMode);
167
viewport()->unsetCursor();
171
bool ImageRegionWidget::capturePointMode() const
173
return d->capturePtMode;
176
void ImageRegionWidget::slotZoomFactorChanged()
178
emit signalContentsMovedEvent(true);
181
void ImageRegionWidget::slotPreviewModeChanged(int mode)
183
d->renderingPreviewMode = mode;
184
updateContentsSize();
185
slotZoomFactorChanged();
188
void ImageRegionWidget::viewportPaintExtraData()
190
if (!m_movingInProgress && !d->pixmapRegion.isNull())
192
QPainter p(viewport());
193
p.setRenderHint(QPainter::Antialiasing, true);
194
p.setBackgroundMode(Qt::TransparentMode);
199
region = getLocalImageRegionToRender();
200
QRect ro(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));
203
QRect rt(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));
205
p.translate(previewRect().topLeft());
207
// Drawing separate view.
209
if (d->renderingPreviewMode == PreviewToolBar::PreviewOriginalImage ||
210
(d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver && !d->onMouseMovePreviewToggled))
212
drawText(&p, QPoint(rt.topLeft().x() + 20, rt.topLeft().y() + 20), i18n("Before"));
214
else if (d->renderingPreviewMode == PreviewToolBar::PreviewTargetImage ||
215
d->renderingPreviewMode == PreviewToolBar::NoPreviewMode ||
216
(d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver && d->onMouseMovePreviewToggled))
218
p.drawPixmap(rt.x(), rt.y(), d->pixmapRegion, 0, 0, rt.width(), rt.height());
220
if (d->renderingPreviewMode == PreviewToolBar::PreviewTargetImage ||
221
d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver)
223
drawText(&p, QPoint(rt.topLeft().x() + 20, rt.topLeft().y() + 20), i18n("After"));
226
else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert ||
227
d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVertCont)
229
if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert)
231
rt.translate(rt.width(), 0);
234
if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVertCont)
236
ro.translate(-ro.width(), 0);
239
p.drawPixmap(rt.x(), rt.y(), d->pixmapRegion, 0, 0, rt.width(), rt.height());
241
p.setPen(QPen(Qt::white, 2, Qt::SolidLine));
242
p.drawLine(rt.topLeft().x(), rt.topLeft().y(), rt.bottomLeft().x(), rt.bottomLeft().y());
243
p.setPen(QPen(Qt::red, 2, Qt::DotLine));
244
p.drawLine(rt.topLeft().x(), rt.topLeft().y() + 1, rt.bottomLeft().x(), rt.bottomLeft().y() - 1);
246
drawText(&p, QPoint(ro.topLeft().x() + 20, ro.topLeft().y() + 20), i18n("Before"));
247
drawText(&p, QPoint(rt.topLeft().x() + 20, rt.topLeft().y() + 20), i18n("After"));
249
else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz ||
250
d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorzCont)
252
if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz)
254
rt.translate(0, rt.height());
257
if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorzCont)
259
ro.translate(0, -ro.height());
262
p.drawPixmap(rt.x(), rt.y(), d->pixmapRegion, 0, 0, rt.width(), rt.height());
264
p.setPen(QPen(Qt::white, 2, Qt::SolidLine));
265
p.drawLine(rt.topLeft().x() + 1, rt.topLeft().y(), rt.topRight().x() - 1, rt.topRight().y());
266
p.setPen(QPen(Qt::red, 2, Qt::DotLine));
267
p.drawLine(rt.topLeft().x() , rt.topLeft().y(), rt.topRight().x() , rt.topRight().y());
269
drawText(&p, QPoint(ro.topLeft().x() + 20, ro.topLeft().y() + 20), i18n("Before"));
270
drawText(&p, QPoint(rt.topLeft().x() + 20, rt.topLeft().y() + 20), i18n("After"));
273
// Drawing highlighted points.
275
if (!d->hightlightPoints.isEmpty())
280
for (int i = 0 ; i < d->hightlightPoints.count() ; ++i)
282
pt = d->hightlightPoints.point(i);
284
if (getOriginalImageRegionToRender().contains(pt))
286
int x = (int)(((double)pt.x() * tileSize()) / floor(tileSize() / zoomFactor()));
287
int y = (int)(((double)pt.y() * tileSize()) / floor(tileSize() / zoomFactor()));
289
QPoint hp(contentsToViewport(QPoint(x, y)));
290
hpArea.setSize(QSize((int)(16 * zoomFactor()), (int)(16 * zoomFactor())));
291
hpArea.moveCenter(hp);
293
p.setPen(QPen(Qt::white, 2, Qt::SolidLine));
294
p.drawLine(hp.x(), hpArea.y(), hp.x(), hp.y() - (int)(3 * zoomFactor()));
295
p.drawLine(hp.x(), hp.y() + (int)(3 * zoomFactor()), hp.x(), hpArea.bottom());
296
p.drawLine(hpArea.x(), hp.y(), hp.x() - (int)(3 * zoomFactor()), hp.y());
297
p.drawLine(hp.x() + (int)(3 * zoomFactor()), hp.y(), hpArea.right(), hp.y());
299
p.setPen(QPen(Qt::red, 2, Qt::DotLine));
300
p.drawLine(hp.x(), hpArea.y(), hp.x(), hp.y() - (int)(3 * zoomFactor()));
301
p.drawLine(hp.x(), hp.y() + (int)(3 * zoomFactor()), hp.x(), hpArea.bottom());
302
p.drawLine(hpArea.x(), hp.y(), hp.x() - (int)(3 * zoomFactor()), hp.y());
303
p.drawLine(hp.x() + (int)(3 * zoomFactor()), hp.y(), hpArea.right(), hp.y());
312
QRect ImageRegionWidget::getLocalImageRegionToRender() const
315
QRect pr = previewRect();
318
int pW = visibleWidth() > pr.width() ? pr.width() : visibleWidth();
319
int pH = visibleHeight() > pr.height() ? pr.height() : visibleHeight();
321
if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVertCont)
323
region = QRect((int)ceilf(contentsX() - pX + visibleWidth() / 2.0),
325
(int)ceilf(pW / 2.0),
328
else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert)
330
region = QRect(contentsX(),
332
(int)ceilf(pW / 2.0),
335
else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorzCont)
337
region = QRect(contentsX(),
338
(int)ceilf(contentsY() - pY + visibleHeight() / 2.0),
340
(int)ceilf(pH / 2.0));
342
else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz)
344
region = QRect(contentsX(),
347
(int)ceilf(pH / 2.0));
351
region = QRect(contentsX(),
360
QRect ImageRegionWidget::getOriginalImageRegion() const
364
switch (d->renderingPreviewMode)
366
case PreviewToolBar::PreviewOriginalImage:
367
case PreviewToolBar::PreviewTargetImage:
368
case PreviewToolBar::PreviewBothImagesVert:
369
case PreviewToolBar::PreviewBothImagesHorz:
370
case PreviewToolBar::PreviewToggleOnMouseOver:
371
region = QRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
374
case PreviewToolBar::PreviewBothImagesVertCont:
375
region = QRect(contentsX(), contentsY(), visibleWidth() / 2, visibleHeight());
378
case PreviewToolBar::PreviewBothImagesHorzCont:
379
region = QRect(contentsX(), contentsY(), visibleWidth(), visibleHeight() / 2);
386
QRect ImageRegionWidget::getOriginalImageRegionToRender() const
388
QRect r = getLocalImageRegionToRender();
390
int x = (int)(((double)r.x() / tileSize()) * floor(tileSize() / zoomFactor()));
391
int y = (int)(((double)r.y() / tileSize()) * floor(tileSize() / zoomFactor()));
392
int w = (int)(((double)r.width() / tileSize()) * floor(tileSize() / zoomFactor()));
393
int h = (int)(((double)r.height() / tileSize()) * floor(tileSize() / zoomFactor()));
395
QRect rect(x, y, w, h);
399
void ImageRegionWidget::setCenterImageRegionPosition()
401
center(contentsWidth() / 2, contentsHeight() / 2);
402
slotZoomFactorChanged();
405
void ImageRegionWidget::setContentsPosition(int x, int y, bool targetDone)
409
m_movingInProgress = false;
412
setContentsPos(x, y);
416
slotZoomFactorChanged();
420
void ImageRegionWidget::backupPixmapRegion()
422
d->pixmapRegion = QPixmap();
425
void ImageRegionWidget::restorePixmapRegion()
427
m_movingInProgress = true;
428
viewport()->repaint();
431
void ImageRegionWidget::setPreviewImage(const DImg& img)
434
QRect r = getLocalImageRegionToRender();
435
image.resize(r.width(), r.height());
437
// Because image plugins are tool witch only work on image data, the DImg container
438
// do not contain metadata from original image. About Color Managed View, we need to
439
// restore the embedded ICC color profile.
440
// However, some plugins may set a profile on the preview image, which we accept of course.
441
if (image.getIccProfile().isNull())
443
image.setIccProfile(d->image.getIccProfile());
446
d->pixmapRegion = d->iface->convertToPixmap(image);
447
repaintContents(false);
450
DImg ImageRegionWidget::getOriginalRegionImage(bool useDownscaledImage) const
452
DImg image = d->image.copy(getOriginalImageRegionToRender());
454
if (useDownscaledImage)
456
QRect r = getLocalImageRegionToRender();
457
image.resize(r.width(), r.height());
463
QImage ImageRegionWidget::previewToQImage() const
465
return d->image.copyQImage();
468
void ImageRegionWidget::slotPanIconSelectionMoved(const QRect& rect, bool targetDone)
470
PreviewWidget::slotPanIconSelectionMoved(rect, targetDone);
471
setContentsPosition((int)(rect.x()*zoomFactor()), (int)(rect.y()*zoomFactor()), targetDone);
474
void ImageRegionWidget::slotContentTakeFocus()
476
PreviewWidget::slotContentTakeFocus();
477
restorePixmapRegion();
480
void ImageRegionWidget::slotContentLeaveFocus()
482
PreviewWidget::slotContentLeaveFocus();
483
setContentsPosition(contentsX(), contentsY(), true);
486
void ImageRegionWidget::slotOriginalImageRegionChanged(bool targetDone)
490
backupPixmapRegion();
491
emit signalOriginalClipFocusChanged();
495
void ImageRegionWidget::exposureSettingsChanged()
498
viewport()->update();
501
void ImageRegionWidget::ICCSettingsChanged()
504
viewport()->update();
507
void ImageRegionWidget::enterEvent(QEvent*)
509
if (d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver)
511
d->onMouseMovePreviewToggled = false;
512
viewport()->repaint();
516
void ImageRegionWidget::leaveEvent(QEvent*)
518
if (d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver)
520
d->onMouseMovePreviewToggled = true;
521
viewport()->repaint();
525
void ImageRegionWidget::contentsMousePressEvent(QMouseEvent* e)
527
if (d->capturePtMode)
529
QRect region = getLocalImageRegionToRender();
531
QRect ro(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));
533
QRect rt(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));
534
QPoint tl = previewRect().topLeft();
538
QPoint pt(contentsToViewport(e->pos()));
540
// Drawing separate view.
542
if (d->renderingPreviewMode == PreviewToolBar::PreviewOriginalImage ||
543
(d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver && !d->onMouseMovePreviewToggled))
547
emitCapturedPointFromOriginal(pt - ro.topLeft());
550
else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert ||
551
d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVertCont)
553
if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert)
555
rt.translate(rt.width(), 0);
558
if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVertCont)
560
ro.translate(-ro.width(), 0);
563
if (!rt.contains(pt) && ro.contains(pt))
565
emitCapturedPointFromOriginal(pt - ro.topLeft());
568
else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz ||
569
d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorzCont)
571
if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz)
573
rt.translate(0, rt.height());
576
if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorzCont)
578
ro.translate(0, -ro.height());
581
if (!rt.contains(pt) && ro.contains(pt))
583
emitCapturedPointFromOriginal(pt - ro.topLeft());
590
PreviewWidget::contentsMousePressEvent(e);
593
void ImageRegionWidget::emitCapturedPointFromOriginal(const QPoint& pt)
595
int x = (int)(((double)pt.x() / tileSize()) * floor(tileSize() / zoomFactor()));
596
int y = (int)(((double)pt.y() / tileSize()) * floor(tileSize() / zoomFactor()));
598
DColor color = d->image.getPixelColor(x, y);
599
kDebug() << "Captured point from image : " << imgPt;
600
emit signalCapturedPointFromOriginal(color, imgPt);
603
void ImageRegionWidget::contentsMouseReleaseEvent(QMouseEvent* e)
605
if (d->capturePtMode)
607
setCapturePointMode(false);
611
PreviewWidget::contentsMouseReleaseEvent(e);
614
} // namespace Digikam