summaryrefslogtreecommitdiffstats
path: root/src/libs/widgets/imageplugins/imageguidewidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/widgets/imageplugins/imageguidewidget.cpp')
-rw-r--r--src/libs/widgets/imageplugins/imageguidewidget.cpp625
1 files changed, 625 insertions, 0 deletions
diff --git a/src/libs/widgets/imageplugins/imageguidewidget.cpp b/src/libs/widgets/imageplugins/imageguidewidget.cpp
new file mode 100644
index 00000000..4ed7f254
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imageguidewidget.cpp
@@ -0,0 +1,625 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-11-16
+ * Description : a widget to display an image with guides
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqregion.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqpixmap.h>
+#include <tqtooltip.h>
+#include <tqtimer.h>
+#include <tqrect.h>
+#include <tqbrush.h>
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdeglobal.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imageguidewidget.h"
+#include "imageguidewidget.moc"
+
+namespace Digikam
+{
+
+class ImageGuideWidgetPriv
+{
+public:
+
+ ImageGuideWidgetPriv()
+ {
+ pixmap = 0;
+ iface = 0;
+ flicker = 0;
+ timerID = 0;
+ focus = false;
+ onMouseMovePreviewToggled = true;
+ renderingPreviewMode = ImageGuideWidget::NoPreviewMode;
+ underExposureIndicator = false;
+ overExposureIndicator = false;
+ }
+
+ bool sixteenBit;
+ bool focus;
+ bool spotVisible;
+ bool onMouseMovePreviewToggled;
+ bool underExposureIndicator;
+ bool overExposureIndicator;
+
+ int width;
+ int height;
+ int timerID;
+ int guideMode;
+ int guideSize;
+ int flicker;
+ int renderingPreviewMode;
+
+ // Current spot position in preview coordinates.
+ TQPoint spot;
+
+ TQRect rect;
+
+ TQColor guideColor;
+
+ TQPixmap *pixmap;
+
+ ImageIface *iface;
+
+ DImg preview;
+};
+
+ImageGuideWidget::ImageGuideWidget(int w, int h, TQWidget *parent,
+ bool spotVisible, int guideMode,
+ const TQColor& guideColor, int guideSize,
+ bool blink, bool useImageSelection)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new ImageGuideWidgetPriv;
+ d->spotVisible = spotVisible;
+ d->guideMode = guideMode;
+ d->guideColor = guideColor;
+ d->guideSize = guideSize;
+
+ setBackgroundMode(TQt::NoBackground);
+ setMinimumSize(w, h);
+ setMouseTracking(true);
+
+ d->iface = new ImageIface(w, h);
+ d->iface->setPreviewType(useImageSelection);
+ uchar *data = d->iface->getPreviewImage();
+ d->width = d->iface->previewWidth();
+ d->height = d->iface->previewHeight();
+ bool sixteenBit = d->iface->previewSixteenBit();
+ bool hasAlpha = d->iface->previewHasAlpha();
+ d->preview = DImg(d->width, d->height, sixteenBit, hasAlpha, data);
+ d->preview.setICCProfil( d->iface->getOriginalImg()->getICCProfil() );
+
+ delete [] data;
+
+ d->pixmap = new TQPixmap(w, h);
+ d->rect = TQRect(w/2-d->width/2, h/2-d->height/2, d->width, d->height);
+
+ resetSpotPosition();
+ setSpotVisible(d->spotVisible, blink);
+}
+
+ImageGuideWidget::~ImageGuideWidget()
+{
+ delete d->iface;
+
+ if (d->timerID)
+ killTimer(d->timerID);
+
+ if (d->pixmap)
+ delete d->pixmap;
+
+ delete d;
+}
+
+ImageIface* ImageGuideWidget::imageIface()
+{
+ return d->iface;
+}
+
+void ImageGuideWidget::slotToggleUnderExposure(bool u)
+{
+ d->underExposureIndicator = u;
+ updatePreview();
+}
+
+void ImageGuideWidget::slotToggleOverExposure(bool o)
+{
+ d->overExposureIndicator = o;
+ updatePreview();
+}
+
+void ImageGuideWidget::resetSpotPosition()
+{
+ d->spot.setX( d->width / 2 );
+ d->spot.setY( d->height / 2 );
+ updatePreview();
+}
+
+void ImageGuideWidget::slotChangeRenderingPreviewMode(int mode)
+{
+ d->renderingPreviewMode = mode;
+ updatePreview();
+}
+
+int ImageGuideWidget::getRenderingPreviewMode()
+{
+ return (d->renderingPreviewMode);
+}
+
+TQPoint ImageGuideWidget::getSpotPosition()
+{
+ return (TQPoint( (int)((float)d->spot.x() * (float)d->iface->originalWidth() / (float)d->width),
+ (int)((float)d->spot.y() * (float)d->iface->originalHeight() / (float)d->height)));
+}
+
+DColor ImageGuideWidget::getSpotColor(int getColorFrom)
+{
+ if (getColorFrom == OriginalImage) // Get point color from full original image
+ return (d->iface->getColorInfoFromOriginalImage(getSpotPosition()));
+ else if (getColorFrom == PreviewImage) // Get point color from full preview image
+ return (d->iface->getColorInfoFromPreviewImage(d->spot));
+
+ // In other cases, get point color from preview target image
+ return (d->iface->getColorInfoFromTargetPreviewImage(d->spot));
+}
+
+void ImageGuideWidget::setSpotVisible(bool spotVisible, bool blink)
+{
+ d->spotVisible = spotVisible;
+
+ if (blink)
+ {
+ if (d->spotVisible)
+ d->timerID = startTimer(800);
+ else
+ {
+ killTimer(d->timerID);
+ d->timerID = 0;
+ }
+ }
+
+ updatePreview();
+}
+
+void ImageGuideWidget::slotChangeGuideColor(const TQColor &color)
+{
+ d->guideColor = color;
+ updatePreview();
+}
+
+void ImageGuideWidget::slotChangeGuideSize(int size)
+{
+ d->guideSize = size;
+ updatePreview();
+}
+
+void ImageGuideWidget::updatePixmap()
+{
+ TQPainter p(d->pixmap);
+ TQString text;
+ TQRect textRect, fontRect;
+ TQFontMetrics fontMt = p.fontMetrics();
+ p.setPen(TQPen(TQt::red, 1)) ;
+
+ d->pixmap->fill(colorGroup().background());
+
+ if (d->renderingPreviewMode == PreviewOriginalImage ||
+ (d->renderingPreviewMode == PreviewToggleOnMouseOver && d->onMouseMovePreviewToggled == false ))
+ {
+ p.drawPixmap(d->rect, d->iface->convertToPixmap(d->preview));
+
+ text = i18n("Original");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20, d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ }
+ else if (d->renderingPreviewMode == PreviewTargetImage || d->renderingPreviewMode == NoPreviewMode ||
+ (d->renderingPreviewMode == PreviewToggleOnMouseOver && d->onMouseMovePreviewToggled == true ))
+ {
+ d->iface->paint(d->pixmap, d->rect.x(), d->rect.y(),
+ d->rect.width(), d->rect.height(),
+ d->underExposureIndicator, d->overExposureIndicator);
+
+ if (d->renderingPreviewMode == PreviewTargetImage ||
+ d->renderingPreviewMode == PreviewToggleOnMouseOver)
+ {
+ text = i18n("Target");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20, d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ }
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesVert ||
+ d->renderingPreviewMode == PreviewBothImagesVertCont)
+ {
+ if (d->renderingPreviewMode == PreviewBothImagesVert)
+ {
+ // Drawing the original image.
+ p.drawPixmap(d->rect, d->iface->convertToPixmap(d->preview));
+
+ // Drawing the target image under the original.
+ d->iface->paint(d->pixmap,
+ d->rect.x()+d->rect.width()/2,
+ d->rect.y(),
+ d->rect.width()/2,
+ d->rect.height(),
+ d->underExposureIndicator,
+ d->overExposureIndicator);
+ }
+ else
+ {
+ // Drawing the target image.
+ d->iface->paint(d->pixmap,
+ d->rect.x(),
+ d->rect.y(),
+ d->rect.width(),
+ d->rect.height(),
+ d->underExposureIndicator,
+ d->overExposureIndicator);
+
+ // Drawing the original image under the target.
+ p.drawPixmap(d->rect.x(), d->rect.y(), d->iface->convertToPixmap(d->preview),
+ 0, 0, d->rect.width()/2, d->rect.height());
+ }
+
+ // Drawing the information and others stuff.
+ p.fillRect(d->rect.right(), 0, width(), height(), colorGroup().background());
+
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(d->rect.x()+d->rect.width()/2-1,
+ d->rect.y(),
+ d->rect.x()+d->rect.width()/2-1,
+ d->rect.y()+d->rect.height());
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(d->rect.x()+d->rect.width()/2-1,
+ d->rect.y(),
+ d->rect.x()+d->rect.width()/2-1,
+ d->rect.y()+d->rect.height());
+
+ p.setPen(TQPen(TQt::red, 1)) ;
+
+ text = i18n("Target");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + d->rect.width()/2 + 20,
+ d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+
+ text = i18n("Original");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20, d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesHorz ||
+ d->renderingPreviewMode == PreviewBothImagesHorzCont)
+ {
+ if (d->renderingPreviewMode == PreviewBothImagesHorz)
+ {
+ // Drawing the original image.
+ p.drawPixmap(d->rect, d->iface->convertToPixmap(d->preview));
+
+ // Drawing the target image under the original.
+ d->iface->paint(d->pixmap,
+ d->rect.x(),
+ d->rect.y()+d->rect.height()/2,
+ d->rect.width(),
+ d->rect.height()/2,
+ d->underExposureIndicator,
+ d->overExposureIndicator);
+ }
+ else
+ {
+ // Drawing the target image.
+ d->iface->paint(d->pixmap,
+ d->rect.x(),
+ d->rect.y(),
+ d->rect.width(),
+ d->rect.height(),
+ d->underExposureIndicator,
+ d->overExposureIndicator);
+
+ // Drawing the original image under the target.
+ p.drawPixmap(d->rect.x(), d->rect.y(), d->iface->convertToPixmap(d->preview),
+ 0, 0, d->rect.width(), d->rect.height()/2);
+ }
+
+ p.fillRect(0, d->rect.bottom(), width(), height(), colorGroup().background());
+
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(d->rect.x(),
+ d->rect.y()+d->rect.height()/2-1,
+ d->rect.x()+d->rect.width(),
+ d->rect.y()+d->rect.height()/2-1);
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(d->rect.x(),
+ d->rect.y()+d->rect.height()/2-1,
+ d->rect.x()+d->rect.width(),
+ d->rect.y()+d->rect.height()/2-1);
+
+ p.setPen(TQPen(TQt::red, 1)) ;
+
+ text = i18n("Target");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20,
+ d->rect.y() + d->rect.height()/2 + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+
+ text = i18n("Original");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20, d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ }
+
+ if (d->spotVisible)
+ {
+ // Adapt spot from image coordinate to widget coordinate.
+ int xspot = d->spot.x() + d->rect.x();
+ int yspot = d->spot.y() + d->rect.y();
+
+ switch (d->guideMode)
+ {
+ case HVGuideMode:
+ {
+ p.setPen(TQPen(TQt::white, d->guideSize, TQt::SolidLine));
+ p.drawLine(xspot, d->rect.top() + d->flicker, xspot, d->rect.bottom() - d->flicker);
+ p.drawLine(d->rect.left() + d->flicker, yspot, d->rect.right() - d->flicker, yspot);
+ p.setPen(TQPen(d->guideColor, d->guideSize, TQt::DotLine));
+ p.drawLine(xspot, d->rect.top() + d->flicker, xspot, d->rect.bottom() - d->flicker);
+ p.drawLine(d->rect.left() + d->flicker, yspot, d->rect.right() - d->flicker, yspot);
+ break;
+ }
+
+ case PickColorMode:
+ {
+ p.setPen(TQPen(d->guideColor, 1, TQt::SolidLine));
+ p.drawLine(xspot-10, yspot-10, xspot+10, yspot+10);
+ p.drawLine(xspot+10, yspot-10, xspot-10, yspot+10);
+ p.setPen(TQPen(d->guideColor, 3, TQt::SolidLine));
+ p.drawEllipse( xspot-5, yspot-5, 11, 11 );
+
+ if (d->flicker%2 != 0)
+ {
+ p.setPen(TQPen(TQt::white, 1, TQt::SolidLine));
+ p.drawEllipse( xspot-5, yspot-5, 11, 11 );
+ }
+
+ break;
+ }
+ }
+ }
+
+ p.end();
+}
+
+void ImageGuideWidget::paintEvent(TQPaintEvent*)
+{
+ bitBlt(this, 0, 0, d->pixmap);
+}
+
+void ImageGuideWidget::updatePreview()
+{
+ updatePixmap();
+ repaint(false);
+}
+
+void ImageGuideWidget::timerEvent(TQTimerEvent* e)
+{
+ if (e->timerId() == d->timerID)
+ {
+ if (d->flicker == 5) d->flicker=0;
+ else d->flicker++;
+ updatePreview();
+ }
+ else
+ TQWidget::timerEvent(e);
+}
+
+void ImageGuideWidget::resizeEvent(TQResizeEvent* e)
+{
+ blockSignals(true);
+ delete d->pixmap;
+ int w = e->size().width();
+ int h = e->size().height();
+ int old_w = d->width;
+ int old_h = d->height;
+
+ uchar *data = d->iface->setPreviewImageSize(w, h);
+ d->width = d->iface->previewWidth();
+ d->height = d->iface->previewHeight();
+ bool sixteenBit = d->iface->previewSixteenBit();
+ bool hasAlpha = d->iface->previewHasAlpha();
+ d->preview = DImg(d->width, d->height, sixteenBit, hasAlpha, data);
+ d->preview.setICCProfil( d->iface->getOriginalImg()->getICCProfil() );
+
+ delete [] data;
+
+ d->pixmap = new TQPixmap(w, h);
+ d->rect = TQRect(w/2-d->width/2, h/2-d->height/2, d->width, d->height);
+
+ d->spot.setX((int)((float)d->spot.x() * ( (float)d->width / (float)old_w)));
+ d->spot.setY((int)((float)d->spot.y() * ( (float)d->height / (float)old_h)));
+ updatePixmap();
+ blockSignals(false);
+ emit signalResized();
+}
+
+void ImageGuideWidget::mousePressEvent(TQMouseEvent* e)
+{
+ if ( !d->focus && e->button() == TQt::LeftButton &&
+ d->rect.contains( e->x(), e->y() ) && d->spotVisible )
+ {
+ d->focus = true;
+ d->spot.setX(e->x()-d->rect.x());
+ d->spot.setY(e->y()-d->rect.y());
+ updatePreview();
+ }
+}
+
+void ImageGuideWidget::mouseReleaseEvent(TQMouseEvent* e)
+{
+ if ( d->rect.contains( e->x(), e->y() ) && d->focus && d->spotVisible)
+ {
+ d->focus = false;
+ updatePreview();
+ d->spot.setX(e->x()-d->rect.x());
+ d->spot.setY(e->y()-d->rect.y());
+
+ DColor color;
+ TQPoint point = getSpotPosition();
+
+ if (d->renderingPreviewMode == PreviewOriginalImage)
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ else if (d->renderingPreviewMode == PreviewTargetImage || d->renderingPreviewMode == NoPreviewMode)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget( color, d->spot );
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesVert)
+ {
+ if (d->spot.x() > d->rect.width()/2)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget(color, TQPoint(d->spot.x() - d->rect.width()/2,
+ d->spot.y()));
+ }
+ else
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesVertCont)
+ {
+ if (d->spot.x() > d->rect.width()/2)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget( color, d->spot);
+ }
+ else
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesHorz)
+ {
+ if (d->spot.y() > d->rect.height()/2)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget(color, TQPoint(d->spot.x(),
+ d->spot.y() - d->rect.height()/2 ));
+ }
+ else
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesHorzCont)
+ {
+ if (d->spot.y() > d->rect.height()/2)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget( color, d->spot);
+ }
+ else
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ }
+ }
+}
+
+void ImageGuideWidget::mouseMoveEvent(TQMouseEvent* e)
+{
+ if ( d->rect.contains( e->x(), e->y() ) && !d->focus && d->spotVisible )
+ {
+ setCursor( KCursor::crossCursor() );
+ }
+ else if ( d->rect.contains( e->x(), e->y() ) && d->focus && d->spotVisible )
+ {
+ d->spot.setX(e->x()-d->rect.x());
+ d->spot.setY(e->y()-d->rect.y());
+ }
+ else
+ {
+ unsetCursor();
+ }
+}
+
+void ImageGuideWidget::enterEvent(TQEvent*)
+{
+ if ( !d->focus && d->renderingPreviewMode == PreviewToggleOnMouseOver )
+ {
+ d->onMouseMovePreviewToggled = false;
+ updatePixmap();
+ repaint(false);
+ }
+}
+
+void ImageGuideWidget::leaveEvent(TQEvent*)
+{
+ if ( !d->focus && d->renderingPreviewMode == PreviewToggleOnMouseOver )
+ {
+ d->onMouseMovePreviewToggled = true;
+ updatePixmap();
+ repaint(false);
+ }
+}
+
+} // NameSpace Digikam