diff options
Diffstat (limited to 'src/libs/widgets/imageplugins/imageguidewidget.cpp')
-rw-r--r-- | src/libs/widgets/imageplugins/imageguidewidget.cpp | 625 |
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 |