/* ============================================================ * * 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 * * 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 #include #include #include #include #include #include #include #include #include // KDE includes. #include #include #include // 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(TQT_TQPAINTDEVICE(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(TQT_TQPAINTDEVICE(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(TQT_TQPAINTDEVICE(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(TQT_TQPAINTDEVICE(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(TQT_TQPAINTDEVICE(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