summaryrefslogtreecommitdiffstats
path: root/src/libs/widgets/imageplugins/imageregionwidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/widgets/imageplugins/imageregionwidget.cpp')
-rw-r--r--src/libs/widgets/imageplugins/imageregionwidget.cpp473
1 files changed, 473 insertions, 0 deletions
diff --git a/src/libs/widgets/imageplugins/imageregionwidget.cpp b/src/libs/widgets/imageplugins/imageregionwidget.cpp
new file mode 100644
index 00000000..c1392cc2
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imageregionwidget.cpp
@@ -0,0 +1,473 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-17
+ * Description : a widget to draw an image clip region.
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqtimer.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqimage.h>
+#include <tqbrush.h>
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+#include <tqpointarray.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdeglobal.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imageregionwidget.h"
+#include "imageregionwidget.moc"
+
+namespace Digikam
+{
+
+class ImageRegionWidgetPriv
+{
+
+public:
+
+ ImageRegionWidgetPriv()
+ {
+ iface = 0;
+ separateView = ImageRegionWidget::SeparateViewVertical;
+ }
+
+ int separateView;
+ int xpos;
+ int ypos;
+
+ TQPixmap pixmapRegion; // Pixmap of current region to render.
+
+ TQPointArray hightlightPoints;
+
+ DImg image; // Entire content image to render pixmap.
+
+ ImageIface *iface;
+};
+
+ImageRegionWidget::ImageRegionWidget(int wp, int hp, TQWidget *parent, bool scrollBar)
+ : PreviewWidget(parent)
+{
+ d = new ImageRegionWidgetPriv;
+ d->iface = new ImageIface(0, 0);
+ d->image = d->iface->getOriginalImg()->copy();
+
+ setMinimumSize(wp, hp);
+ setBackgroundColor(colorGroup().background());
+
+ if( !scrollBar )
+ {
+ setVScrollBarMode( TQScrollView::AlwaysOff );
+ setHScrollBarMode( TQScrollView::AlwaysOff );
+ }
+
+ connect(this, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SLOT(slotZoomFactorChanged()));
+}
+
+ImageRegionWidget::~ImageRegionWidget()
+{
+ if (d->iface) delete d->iface;
+ delete d;
+}
+
+void ImageRegionWidget::resizeEvent(TQResizeEvent* e)
+{
+ if (!e) return;
+
+ TQScrollView::resizeEvent(e);
+
+ // NOTE: We will always adapt the min. zoom factor to the visible size of canvas
+
+ double srcWidth = previewWidth();
+ double srcHeight = previewHeight();
+ double dstWidth = contentsRect().width();
+ double dstHeight = contentsRect().height();
+ double zoom = TQMAX(dstWidth/srcWidth, dstHeight/srcHeight);
+
+ setZoomMin(zoom);
+ setZoomMax(zoom*12.0);
+ setZoomFactor(zoom);
+}
+
+int ImageRegionWidget::previewWidth()
+{
+ return d->image.width();
+}
+
+int ImageRegionWidget::previewHeight()
+{
+ return d->image.height();
+}
+
+bool ImageRegionWidget::previewIsNull()
+{
+ return d->image.isNull();
+}
+
+void ImageRegionWidget::resetPreview()
+{
+ d->image.reset();
+}
+
+void ImageRegionWidget::paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh)
+{
+ DImg img = d->image.smoothScaleSection(sx, sy, sw, sh, tileSize(), tileSize());
+ TQPixmap pix2 = d->iface->convertToPixmap(img);
+ bitBlt(pix, 0, 0, &pix2, 0, 0);
+}
+
+void ImageRegionWidget::setHighLightPoints(const TQPointArray& pointsList)
+{
+ d->hightlightPoints = pointsList;
+ repaintContents(false);
+}
+
+void ImageRegionWidget::slotZoomFactorChanged()
+{
+ emit signalContentsMovedEvent(true);
+}
+
+void ImageRegionWidget::slotSeparateViewToggled(int mode)
+{
+ d->separateView = mode;
+ updateContentsSize();
+ slotZoomFactorChanged();
+}
+
+TQRect ImageRegionWidget::getImageRegion()
+{
+ TQRect region;
+
+ switch (d->separateView)
+ {
+ case SeparateViewVertical:
+ case SeparateViewHorizontal:
+ case SeparateViewNone:
+ region = TQRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
+ break;
+ case SeparateViewDuplicateVert:
+ region = TQRect(contentsX(), contentsY(), visibleWidth()/2, visibleHeight());
+ break;
+ case SeparateViewDuplicateHorz:
+ region = TQRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()/2);
+ break;
+ }
+
+ return region;
+}
+
+void ImageRegionWidget::viewportPaintExtraData()
+{
+ if (!m_movingInProgress && !d->pixmapRegion.isNull())
+ {
+ TQPainter p(viewport());
+ TQRect region = getLocalTargetImageRegion();
+ TQRect rt(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));
+
+ region = getLocalImageRegionToRender();
+ TQRect ro(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));
+
+ bitBlt(viewport(), rt.x(), rt.y(), &d->pixmapRegion, 0, 0, rt.width(), rt.height());
+
+ // Drawing separate view.
+
+ switch (d->separateView)
+ {
+ case SeparateViewVertical:
+ case SeparateViewDuplicateVert:
+ {
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(rt.topLeft().x(), rt.topLeft().y(),
+ rt.bottomLeft().x(), rt.bottomLeft().y());
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(rt.topLeft().x(), rt.topLeft().y()+1,
+ rt.bottomLeft().x(), rt.bottomLeft().y()-1);
+
+ p.setPen(TQPen(TQt::red, 1)) ;
+ TQFontMetrics fontMt = p.fontMetrics();
+
+ TQString text(i18n("Target"));
+ TQRect textRect;
+ TQRect fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text);
+ textRect.setTopLeft(TQPoint(rt.topLeft().x()+20, rt.topLeft().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, contentsWidth(), contentsHeight(), 0, text);
+
+ if (d->separateView == SeparateViewVertical)
+ ro.moveBy(-ro.width(), 0);
+
+ textRect.setTopLeft(TQPoint(ro.topLeft().x()+20, ro.topLeft().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);
+ break;
+ }
+ case SeparateViewHorizontal:
+ case SeparateViewDuplicateHorz:
+ {
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(rt.topLeft().x()+1, rt.topLeft().y(),
+ rt.topRight().x()-1, rt.topRight().y());
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(rt.topLeft().x(), rt.topLeft().y(),
+ rt.topRight().x(), rt.topRight().y());
+
+ p.setPen(TQPen(TQt::red, 1)) ;
+ TQFontMetrics fontMt = p.fontMetrics();
+
+ TQString text(i18n("Target"));
+ TQRect textRect;
+ TQRect fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text);
+ textRect.setTopLeft(TQPoint(rt.topLeft().x()+20, rt.topLeft().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, contentsWidth(), contentsHeight(), 0, text);
+
+ if (d->separateView == SeparateViewHorizontal)
+ ro.moveBy(0, -ro.height());
+
+ textRect.setTopLeft(TQPoint(ro.topLeft().x()+20, ro.topLeft().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);
+ break;
+ }
+ }
+
+ // Drawing HighLighted points.
+
+ if (!d->hightlightPoints.isEmpty())
+ {
+ TQPoint pt;
+ TQRect hpArea;
+
+ for (int i = 0 ; i < d->hightlightPoints.count() ; i++)
+ {
+ pt = d->hightlightPoints.point(i);
+
+ if ( getImageRegionToRender().contains(pt) )
+ {
+ int x = (int)(((double)pt.x() * tileSize()) / floor(tileSize() / zoomFactor()));
+ int y = (int)(((double)pt.y() * tileSize()) / floor(tileSize() / zoomFactor()));
+
+ TQPoint hp(contentsToViewport(TQPoint(x, y)));
+ hpArea.setSize(TQSize((int)(16*zoomFactor()), (int)(16*zoomFactor())));
+ hpArea.moveCenter(hp);
+
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(hp.x(), hpArea.y(),
+ hp.x(), hp.y()-(int)(3*zoomFactor()));
+ p.drawLine(hp.x(), hp.y()+(int)(3*zoomFactor()),
+ hp.x(), hpArea.bottom());
+ p.drawLine(hpArea.x(), hp.y(),
+ hp.x()-(int)(3*zoomFactor()), hp.y());
+ p.drawLine(hp.x()+(int)(3*zoomFactor()), hp.y(),
+ hpArea.right(), hp.y());
+
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(hp.x(), hpArea.y(),
+ hp.x(), hp.y()-(int)(3*zoomFactor()));
+ p.drawLine(hp.x(), hp.y()+(int)(3*zoomFactor()),
+ hp.x(), hpArea.bottom());
+ p.drawLine(hpArea.x(), hp.y(),
+ hp.x()-(int)(3*zoomFactor()), hp.y());
+ p.drawLine(hp.x()+(int)(3*zoomFactor()), hp.y(),
+ hpArea.right(), hp.y());
+ }
+ }
+ }
+ p.end();
+ }
+}
+
+void ImageRegionWidget::setCenterContentsPosition()
+{
+ center(contentsWidth()/2, contentsHeight()/2);
+ slotZoomFactorChanged();
+}
+
+void ImageRegionWidget::setContentsPosition(int x, int y, bool targetDone)
+{
+ if( targetDone )
+ m_movingInProgress = false;
+
+ setContentsPos(x, y);
+
+ if( targetDone )
+ slotZoomFactorChanged();
+}
+
+void ImageRegionWidget::backupPixmapRegion()
+{
+ d->pixmapRegion = TQPixmap();
+}
+
+void ImageRegionWidget::restorePixmapRegion()
+{
+ m_movingInProgress = true;
+ viewport()->repaint(false);
+}
+
+void ImageRegionWidget::updatePreviewImage(DImg *img)
+{
+ DImg image = img->copy();
+ TQRect r = getLocalImageRegionToRender();
+ image.resize(r.width(), r.height());
+
+ // Because image plugins are tool witch only work on image data, the DImg container
+ // do not contain metadata from original image. About Color Managed View, we need to
+ // restore the embedded ICC color profile.
+ image.setICCProfil(d->image.getICCProfil());
+ d->pixmapRegion = d->iface->convertToPixmap(image);
+}
+
+DImg ImageRegionWidget::getImageRegionImage()
+{
+ return (d->image.copy(getImageRegionToRender()));
+}
+
+TQRect ImageRegionWidget::getImageRegionToRender()
+{
+ TQRect r = getLocalImageRegionToRender();
+
+ int x = (int)(((double)r.x() / tileSize()) * floor(tileSize() / zoomFactor()));
+ int y = (int)(((double)r.y() / tileSize()) * floor(tileSize() / zoomFactor()));
+ int w = (int)(((double)r.width() / tileSize()) * floor(tileSize() / zoomFactor()));
+ int h = (int)(((double)r.height() / tileSize()) * floor(tileSize() / zoomFactor()));
+
+ TQRect rect(x, y, w, h);
+ return (rect);
+}
+
+TQRect ImageRegionWidget::getLocalImageRegionToRender()
+{
+ TQRect region;
+
+ if (d->separateView == SeparateViewVertical)
+ {
+ region = TQRect((int)ceilf(contentsX()+visibleWidth()/2.0), contentsY(),
+ (int)ceilf(visibleWidth()/2.0), visibleHeight());
+ }
+ else if (d->separateView == SeparateViewHorizontal)
+ {
+ region = TQRect(contentsX(), (int)ceilf(contentsY()+visibleHeight()/2.0),
+ visibleWidth(), (int)ceilf(visibleHeight()/2.0));
+ }
+ else if (d->separateView == SeparateViewDuplicateVert)
+ {
+ region = TQRect(contentsX(), contentsY(),
+ (int)ceilf(visibleWidth()/2.0), visibleHeight());
+ }
+ else if (d->separateView == SeparateViewDuplicateHorz)
+ {
+ region = TQRect(contentsX(), contentsY(),
+ visibleWidth(), (int)ceilf(visibleHeight()/2.0));
+ }
+ else
+ {
+ region = TQRect(contentsX(), contentsY(),
+ visibleWidth(), visibleHeight());
+ }
+
+ return (region);
+}
+
+TQRect ImageRegionWidget::getLocalTargetImageRegion()
+{
+ TQRect region = getLocalImageRegionToRender();
+
+ if (d->separateView == SeparateViewDuplicateVert)
+ region.moveBy(region.width(), 0);
+ else if (d->separateView == SeparateViewDuplicateHorz)
+ region.moveBy(0, region.height());
+
+ return region;
+}
+
+void ImageRegionWidget::setContentsSize()
+{
+ switch (d->separateView)
+ {
+ case SeparateViewVertical:
+ case SeparateViewHorizontal:
+ case SeparateViewNone:
+ {
+ PreviewWidget::setContentsSize();
+ break;
+ }
+ case SeparateViewDuplicateVert:
+ {
+ resizeContents(zoomWidth()+visibleWidth()/2, zoomHeight());
+ break;
+ }
+ case SeparateViewDuplicateHorz:
+ {
+ resizeContents(zoomWidth(), zoomHeight()+visibleHeight()/2);
+ break;
+ }
+ default:
+ DWarning() << "Unknown separation view specified" << endl;
+ }
+}
+
+void ImageRegionWidget::contentsWheelEvent(TQWheelEvent *e)
+{
+ e->accept();
+
+ if (e->state() & TQt::ControlButton)
+ {
+ if (e->delta() < 0 && !maxZoom())
+ slotIncreaseZoom();
+ else if (e->delta() > 0 && !minZoom())
+ slotDecreaseZoom();
+ return;
+ }
+}
+
+} // NameSpace Digikam