summaryrefslogtreecommitdiffstats
path: root/src/imageplugins/perspective
diff options
context:
space:
mode:
Diffstat (limited to 'src/imageplugins/perspective')
-rw-r--r--src/imageplugins/perspective/Makefile.am35
-rw-r--r--src/imageplugins/perspective/digikamimageplugin_perspective.desktop52
-rw-r--r--src/imageplugins/perspective/digikamimageplugin_perspective_ui.rc20
-rw-r--r--src/imageplugins/perspective/imageeffect_perspective.cpp252
-rw-r--r--src/imageplugins/perspective/imageeffect_perspective.h89
-rw-r--r--src/imageplugins/perspective/imageplugin_perspective.cpp69
-rw-r--r--src/imageplugins/perspective/imageplugin_perspective.h56
-rw-r--r--src/imageplugins/perspective/matrix.cpp177
-rw-r--r--src/imageplugins/perspective/matrix.h106
-rw-r--r--src/imageplugins/perspective/perspectivetool.cpp244
-rw-r--r--src/imageplugins/perspective/perspectivetool.h100
-rw-r--r--src/imageplugins/perspective/perspectivewidget.cpp839
-rw-r--r--src/imageplugins/perspective/perspectivewidget.h172
-rw-r--r--src/imageplugins/perspective/triangle.cpp65
-rw-r--r--src/imageplugins/perspective/triangle.h57
15 files changed, 2333 insertions, 0 deletions
diff --git a/src/imageplugins/perspective/Makefile.am b/src/imageplugins/perspective/Makefile.am
new file mode 100644
index 00000000..028add37
--- /dev/null
+++ b/src/imageplugins/perspective/Makefile.am
@@ -0,0 +1,35 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_perspective_la_SOURCES = imageplugin_perspective.cpp \
+ perspectivetool.cpp \
+ perspectivewidget.cpp triangle.cpp matrix.cpp
+
+digikamimageplugin_perspective_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_perspective_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_perspective.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_perspective.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_perspective_ui.rc
+
diff --git a/src/imageplugins/perspective/digikamimageplugin_perspective.desktop b/src/imageplugins/perspective/digikamimageplugin_perspective.desktop
new file mode 100644
index 00000000..a6fcc4d3
--- /dev/null
+++ b/src/imageplugins/perspective/digikamimageplugin_perspective.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_Perspective
+Name[bg]=Приставка за снимки - Перспектива
+Name[da]=Billedplugin_Perspektivværktøj
+Name[el]=ΠρόσθετοΕικόνας_Προοπτική
+Name[fi]=Perspektiivimuunnos
+Name[hr]=Perspektiva
+Name[it]=PluginImmagini_Prospettiva
+Name[nl]=Afbeeldingsplugin_Perspectief
+Name[sr]=Перспектива
+Name[sr@Latn]=Perspektiva
+Name[sv]=Insticksprogram för perspektiv
+Name[tr]=ResimEklentisi_Perspektif
+Name[xx]=xxImagePlugin_Perspectivexx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Perspective tool plugin for digiKam
+Comment[bg]=Приставка на digiKam за промяна на перспективата
+Comment[ca]=Connector pel digiKam d'eina de perspectiva
+Comment[da]=Perspektivværktøjs-plugin for Digikam
+Comment[de]=digiKam-Modul zum Justieren der Perspektive eines Bildes
+Comment[el]=Πρόσθετο εργαλείο προοπτικής για το digiKam
+Comment[es]=Plugin para digiKam de herramientas de perspectiva
+Comment[et]=DigiKami perspektiiviplugin
+Comment[fa]=وصلۀ ابزار منظره برای digiKam
+Comment[fi]=Vääristää kuvan perspektiiviä
+Comment[fr]=Module externe pour modifier la perspective dans digiKam
+Comment[gl]=Un plugin de digiKam para a ferramenta de perspectiva
+Comment[hr]=digiKam dodatak za perspektivu
+Comment[it]=Plugin per lo strumento di prospettiva per digiKam
+Comment[ja]=digiKam 視点調整プラグイン
+Comment[ms]=Plugin alatan perspektif untuk digiKam
+Comment[nds]=digiKam-Moduul för den Kietwinkel
+Comment[nl]=Digikam-plugin voor perspectiefaanpassing
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਪਰੋਸਪੈਕਟਿਵ ਸੰਦ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam umożliwiająca korekcję perspektywy
+Comment[pt]=Um 'plugin' do digiKam para a ferramenta de perspectiva
+Comment[pt_BR]=Plugin de ferramenta de Perspectiva
+Comment[ru]=Модуль изменения перспективы для digiKam
+Comment[sk]=digiKam plugin pre nástroj s perspektívou
+Comment[sr]=digiKam-ов прикључак за перспективу
+Comment[sr@Latn]=digiKam-ov priključak za perspektivu
+Comment[sv]=Digikam insticksprogram med perspektivverktyg
+Comment[tr]=digiKam için perspektif aracı eklentisi
+Comment[uk]=Втулок засобу побудови перспективи для digiKam
+Comment[vi]=Phần bổ sung công cụ phối cảnh cho digiKam
+Comment[xx]=xxPerspective tool plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_perspective
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/perspective/digikamimageplugin_perspective_ui.rc b/src/imageplugins/perspective/digikamimageplugin_perspective_ui.rc
new file mode 100644
index 00000000..0f3bca57
--- /dev/null
+++ b/src/imageplugins/perspective/digikamimageplugin_perspective_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="4" name="digikamimageplugin_perspective" >
+
+ <MenuBar>
+
+ <Menu name="Transform" ><text>Tra&amp;nsform</text>
+ <Action name="imageplugin_perspective" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_perspective" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/perspective/imageeffect_perspective.cpp b/src/imageplugins/perspective/imageeffect_perspective.cpp
new file mode 100644
index 00000000..15bef877
--- /dev/null
+++ b/src/imageplugins/perspective/imageeffect_perspective.cpp
@@ -0,0 +1,252 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective .
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * 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 <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqspinbox.h>
+#include <tqpushbutton.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqcheckbox.h>
+
+// KDE includes.
+
+#include <kcolorbutton.h>
+#include <kcursor.h>
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <kseparator.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "perspectivewidget.h"
+#include "imageeffect_perspective.h"
+#include "imageeffect_perspective.moc"
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+ImageEffect_Perspective::ImageEffect_Perspective(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Adjust Photograph Perspective"),
+ "perspective", false, false)
+{
+ TQString whatsThis;
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Perspective"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to process image perspective adjustment."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2006, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(plainPage());
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* l = new TQVBoxLayout(frame, 5, 0);
+ m_previewWidget = new PerspectiveWidget(525, 350, frame);
+ l->addWidget(m_previewWidget);
+ TQWhatsThis::add( m_previewWidget, i18n("<p>This is the perspective transformation operation preview. "
+ "You can use the mouse for dragging the corner to adjust the "
+ "perspective transformation area."));
+ setPreviewAreaWidget(frame);
+
+ // -------------------------------------------------------------
+
+ TQString temp;
+ Digikam::ImageIface iface(0, 0);
+
+ TQWidget *gbox2 = new TQWidget(plainPage());
+ TQGridLayout *gridLayout = new TQGridLayout( gbox2, 13, 2, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("New width:"), gbox2);
+ m_newWidthLabel = new TQLabel(temp.setNum( iface.originalWidth()) + i18n(" px"), gbox2);
+ m_newWidthLabel->setAlignment( AlignBottom | AlignRight );
+
+ TQLabel *label2 = new TQLabel(i18n("New height:"), gbox2);
+ m_newHeightLabel = new TQLabel(temp.setNum( iface.originalHeight()) + i18n(" px"), gbox2);
+ m_newHeightLabel->setAlignment( AlignBottom | AlignRight );
+
+ gridLayout->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridLayout->addMultiCellWidget(m_newWidthLabel, 0, 0, 1, 2);
+ gridLayout->addMultiCellWidget(label2, 1, 1, 0, 0);
+ gridLayout->addMultiCellWidget(m_newHeightLabel, 1, 1, 1, 2);
+
+ // -------------------------------------------------------------
+
+ KSeparator *line = new KSeparator(Horizontal, gbox2);
+
+ TQLabel *angleLabel = new TQLabel(i18n("Angles (in degrees):"), gbox2);
+ TQLabel *label3 = new TQLabel(i18n(" Top left:"), gbox2);
+ m_topLeftAngleLabel = new TQLabel(gbox2);
+ TQLabel *label4 = new TQLabel(i18n(" Top right:"), gbox2);
+ m_topRightAngleLabel = new TQLabel(gbox2);
+ TQLabel *label5 = new TQLabel(i18n(" Bottom left:"), gbox2);
+ m_bottomLeftAngleLabel = new TQLabel(gbox2);
+ TQLabel *label6 = new TQLabel(i18n(" Bottom right:"), gbox2);
+ m_bottomRightAngleLabel = new TQLabel(gbox2);
+
+ gridLayout->addMultiCellWidget(line, 2, 2, 0, 2);
+ gridLayout->addMultiCellWidget(angleLabel, 3, 3, 0, 2);
+ gridLayout->addMultiCellWidget(label3, 4, 4, 0, 0);
+ gridLayout->addMultiCellWidget(m_topLeftAngleLabel, 4, 4, 1, 2);
+ gridLayout->addMultiCellWidget(label4, 5, 5, 0, 0);
+ gridLayout->addMultiCellWidget(m_topRightAngleLabel, 5, 5, 1, 2);
+ gridLayout->addMultiCellWidget(label5, 6, 6, 0, 0);
+ gridLayout->addMultiCellWidget(m_bottomLeftAngleLabel, 6, 6, 1, 2);
+ gridLayout->addMultiCellWidget(label6, 7, 7, 0, 0);
+ gridLayout->addMultiCellWidget(m_bottomRightAngleLabel, 7, 7, 1, 2);
+
+ // -------------------------------------------------------------
+
+ KSeparator *line2 = new KSeparator(Horizontal, gbox2);
+
+ m_drawWhileMovingCheckBox = new TQCheckBox(i18n("Draw preview while moving"), gbox2);
+ gridLayout->addMultiCellWidget(line2, 8, 8, 0, 2);
+ gridLayout->addMultiCellWidget(m_drawWhileMovingCheckBox, 9, 9, 0, 2);
+
+ m_drawGridCheckBox = new TQCheckBox(i18n("Draw grid"), gbox2);
+ gridLayout->addMultiCellWidget(m_drawGridCheckBox, 10, 10, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label7 = new TQLabel(i18n("Guide color:"), gbox2);
+ m_guideColorBt = new KColorButton( TQColor( TQt::red ), gbox2 );
+ TQWhatsThis::add( m_guideColorBt, i18n("<p>Set here the color used to draw guides dashed-lines."));
+ gridLayout->addMultiCellWidget(label7, 11, 11, 0, 0);
+ gridLayout->addMultiCellWidget(m_guideColorBt, 11, 11, 2, 2);
+
+ TQLabel *label8 = new TQLabel(i18n("Guide width:"), gbox2);
+ m_guideSize = new TQSpinBox( 1, 5, 1, gbox2);
+ TQWhatsThis::add( m_guideSize, i18n("<p>Set here the width in pixels used to draw guides dashed-lines."));
+ gridLayout->addMultiCellWidget(label8, 12, 12, 0, 0);
+ gridLayout->addMultiCellWidget(m_guideSize, 12, 12, 2, 2);
+
+ gridLayout->setColStretch(1, 10);
+ gridLayout->setRowStretch(13, 10);
+
+ setUserAreaWidget(gbox2);
+
+ // -------------------------------------------------------------
+
+ connect(m_previewWidget, TQ_SIGNAL(signalPerspectiveChanged(TQRect, float, float, float, float)),
+ this, TQ_SLOT(slotUpdateInfo(TQRect, float, float, float, float)));
+
+ connect(m_drawWhileMovingCheckBox, TQ_SIGNAL(toggled(bool)),
+ m_previewWidget, TQ_SLOT(slotToggleDrawWhileMoving(bool)));
+
+ connect(m_drawGridCheckBox, TQ_SIGNAL(toggled(bool)),
+ m_previewWidget, TQ_SLOT(slotToggleDrawGrid(bool)));
+
+ connect(m_guideColorBt, TQ_SIGNAL(changed(const TQColor &)),
+ m_previewWidget, TQ_SLOT(slotChangeGuideColor(const TQColor &)));
+
+ connect(m_guideSize, TQ_SIGNAL(valueChanged(int)),
+ m_previewWidget, TQ_SLOT(slotChangeGuideSize(int)));
+}
+
+ImageEffect_Perspective::~ImageEffect_Perspective()
+{
+}
+
+void ImageEffect_Perspective::readUserSettings(void)
+{
+ TQColor defaultGuideColor(TQt::red);
+ TDEConfig *config = kapp->config();
+ config->setGroup("perspective Tool Dialog");
+ m_drawWhileMovingCheckBox->setChecked(config->readBoolEntry("Draw While Moving", true));
+ m_drawGridCheckBox->setChecked(config->readBoolEntry("Draw Grid", false));
+ m_guideColorBt->setColor(config->readColorEntry("Guide Color", &defaultGuideColor));
+ m_guideSize->setValue(config->readNumEntry("Guide Width", 1));
+ m_previewWidget->slotToggleDrawWhileMoving(m_drawWhileMovingCheckBox->isChecked());
+ m_previewWidget->slotToggleDrawGrid(m_drawGridCheckBox->isChecked());
+ m_previewWidget->slotChangeGuideColor(m_guideColorBt->color());
+ m_previewWidget->slotChangeGuideSize(m_guideSize->value());
+}
+
+void ImageEffect_Perspective::writeUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("perspective Tool Dialog");
+ config->writeEntry("Draw While Moving", m_drawWhileMovingCheckBox->isChecked());
+ config->writeEntry("Draw Grid", m_drawGridCheckBox->isChecked());
+ config->writeEntry("Guide Color", m_guideColorBt->color());
+ config->writeEntry("Guide Width", m_guideSize->value());
+ config->sync();
+}
+
+void ImageEffect_Perspective::resetValues()
+{
+ m_previewWidget->reset();
+}
+
+void ImageEffect_Perspective::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ m_previewWidget->applyPerspectiveAdjustment();
+ accept();
+ kapp->restoreOverrideCursor();
+}
+
+void ImageEffect_Perspective::slotUpdateInfo(TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle)
+{
+ TQString temp;
+ m_newWidthLabel->setText(temp.setNum( newSize.width()) + i18n(" px") );
+ m_newHeightLabel->setText(temp.setNum( newSize.height()) + i18n(" px") );
+
+ m_topLeftAngleLabel->setText(temp.setNum( topLeftAngle, 'f', 1 ));
+ m_topRightAngleLabel->setText(temp.setNum( topRightAngle, 'f', 1 ));
+ m_bottomLeftAngleLabel->setText(temp.setNum( bottomLeftAngle, 'f', 1 ));
+ m_bottomRightAngleLabel->setText(temp.setNum( bottomRightAngle, 'f', 1 ));
+}
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
diff --git a/src/imageplugins/perspective/imageeffect_perspective.h b/src/imageplugins/perspective/imageeffect_perspective.h
new file mode 100644
index 00000000..41388aa7
--- /dev/null
+++ b/src/imageplugins/perspective/imageeffect_perspective.h
@@ -0,0 +1,89 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective .
+ *
+ * Copyright (C) 2005-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.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_PERSPECTIVE_H
+#define IMAGEEFFECT_PERSPECTIVE_H
+
+// TQt includes.
+
+#include <tqrect.h>
+
+// Digikam includes.
+
+#include "imagedlgbase.h"
+
+class TQLabel;
+class TQCheckBox;
+class TQSpinBox;
+
+class KColorButton;
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class PerspectiveWidget;
+
+class ImageEffect_Perspective : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Perspective(TQWidget* parent);
+ ~ImageEffect_Perspective();
+
+private slots:
+
+ void slotUpdateInfo(TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle);
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void finalRendering();
+
+private:
+
+ TQLabel *m_newWidthLabel;
+ TQLabel *m_newHeightLabel;
+ TQLabel *m_topLeftAngleLabel;
+ TQLabel *m_topRightAngleLabel;
+ TQLabel *m_bottomLeftAngleLabel;
+ TQLabel *m_bottomRightAngleLabel;
+
+ TQCheckBox *m_drawWhileMovingCheckBox;
+ TQCheckBox *m_drawGridCheckBox;
+
+ TQSpinBox *m_guideSize;
+
+ KColorButton *m_guideColorBt;
+
+ PerspectiveWidget *m_previewWidget;
+};
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
+#endif /* IMAGEEFFECT_PERSPECTIVE_H */
diff --git a/src/imageplugins/perspective/imageplugin_perspective.cpp b/src/imageplugins/perspective/imageplugin_perspective.cpp
new file mode 100644
index 00000000..bb5d0444
--- /dev/null
+++ b/src/imageplugins/perspective/imageplugin_perspective.cpp
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective .
+ *
+ * Copyright (C) 2005-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.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "perspectivetool.h"
+#include "imageplugin_perspective.h"
+#include "imageplugin_perspective.moc"
+
+using namespace DigikamPerspectiveImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_perspective,
+ KGenericFactory<ImagePlugin_Perspective>("digikamimageplugin_perspective"));
+
+ImagePlugin_Perspective::ImagePlugin_Perspective(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_Perspective")
+{
+ m_perspectiveAction = new TDEAction(i18n("Perspective Adjustment..."), "perspective", 0,
+ this, TQ_SLOT(slotPerspective()),
+ actionCollection(), "imageplugin_perspective");
+
+ setXMLFile("digikamimageplugin_perspective_ui.rc");
+
+ DDebug() << "ImagePlugin_Perspective plugin loaded" << endl;
+}
+
+ImagePlugin_Perspective::~ImagePlugin_Perspective()
+{
+}
+
+void ImagePlugin_Perspective::setEnabledActions(bool enable)
+{
+ m_perspectiveAction->setEnabled(enable);
+}
+
+void ImagePlugin_Perspective::slotPerspective()
+{
+ PerspectiveTool *tool = new PerspectiveTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/perspective/imageplugin_perspective.h b/src/imageplugins/perspective/imageplugin_perspective.h
new file mode 100644
index 00000000..5dee7b1b
--- /dev/null
+++ b/src/imageplugins/perspective/imageplugin_perspective.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective .
+ *
+ * Copyright (C) 2005-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.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_PERSPECTIVE_H
+#define IMAGEPLUGIN_PERSPECTIVE_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_Perspective : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_Perspective(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_Perspective();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotPerspective();
+
+private:
+
+ TDEAction *m_perspectiveAction;
+};
+
+#endif /* IMAGEPLUGIN_PERSPECTIVE_H */
diff --git a/src/imageplugins/perspective/matrix.cpp b/src/imageplugins/perspective/matrix.cpp
new file mode 100644
index 00000000..65723c56
--- /dev/null
+++ b/src/imageplugins/perspective/matrix.cpp
@@ -0,0 +1,177 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a matrix implementation for image
+ * perspective adjustment.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Matrix3 implementation inspired from gimp 2.0
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <cstring>
+
+// Local includes.
+
+#include "matrix.h"
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+static double identityMatrix[3][3] = { { 1.0, 0.0, 0.0 },
+ { 0.0, 1.0, 0.0 },
+ { 0.0, 0.0, 1.0 } };
+
+Matrix::Matrix()
+{
+ memcpy(coeff, identityMatrix, sizeof(coeff));
+}
+
+void Matrix::translate (double x, double y)
+{
+ double g, h, i;
+
+ g = coeff[2][0];
+ h = coeff[2][1];
+ i = coeff[2][2];
+
+ coeff[0][0] += x * g;
+ coeff[0][1] += x * h;
+ coeff[0][2] += x * i;
+ coeff[1][0] += y * g;
+ coeff[1][1] += y * h;
+ coeff[1][2] += y * i;
+}
+
+void Matrix::scale(double x, double y)
+{
+ coeff[0][0] *= x;
+ coeff[0][1] *= x;
+ coeff[0][2] *= x;
+
+ coeff[1][0] *= y;
+ coeff[1][1] *= y;
+ coeff[1][2] *= y;
+}
+
+void Matrix::multiply(const Matrix &matrix)
+{
+ int i, j;
+ Matrix tmp;
+ double t1, t2, t3;
+
+ for (i = 0; i < 3; i++)
+ {
+ t1 = matrix.coeff[i][0];
+ t2 = matrix.coeff[i][1];
+ t3 = matrix.coeff[i][2];
+
+ for (j = 0; j < 3; j++)
+ {
+ tmp.coeff[i][j] = t1 * coeff[0][j];
+ tmp.coeff[i][j] += t2 * coeff[1][j];
+ tmp.coeff[i][j] += t3 * coeff[2][j];
+ }
+ }
+
+ *this = tmp;
+}
+
+void Matrix::transformPoint(double x, double y, double *newx, double *newy) const
+{
+ double w;
+
+ w = coeff[2][0] * x + coeff[2][1] * y + coeff[2][2];
+
+ if (w == 0.0)
+ w = 1.0;
+ else
+ w = 1.0/w;
+
+ *newx = (coeff[0][0] * x +
+ coeff[0][1] * y +
+ coeff[0][2]) * w;
+ *newy = (coeff[1][0] * x +
+ coeff[1][1] * y +
+ coeff[1][2]) * w;
+}
+
+void Matrix::invert()
+{
+ Matrix inv;
+ double det;
+
+ det = determinant();
+
+ if (det == 0.0)
+ return;
+
+ det = 1.0 / det;
+
+ inv.coeff[0][0] = (coeff[1][1] * coeff[2][2] -
+ coeff[1][2] * coeff[2][1]) * det;
+
+ inv.coeff[1][0] = - (coeff[1][0] * coeff[2][2] -
+ coeff[1][2] * coeff[2][0]) * det;
+
+ inv.coeff[2][0] = (coeff[1][0] * coeff[2][1] -
+ coeff[1][1] * coeff[2][0]) * det;
+
+ inv.coeff[0][1] = - (coeff[0][1] * coeff[2][2] -
+ coeff[0][2] * coeff[2][1]) * det;
+
+ inv.coeff[1][1] = (coeff[0][0] * coeff[2][2] -
+ coeff[0][2] * coeff[2][0]) * det;
+
+ inv.coeff[2][1] = - (coeff[0][0] * coeff[2][1] -
+ coeff[0][1] * coeff[2][0]) * det;
+
+ inv.coeff[0][2] = (coeff[0][1] * coeff[1][2] -
+ coeff[0][2] * coeff[1][1]) * det;
+
+ inv.coeff[1][2] = - (coeff[0][0] * coeff[1][2] -
+ coeff[0][2] * coeff[1][0]) * det;
+
+ inv.coeff[2][2] = (coeff[0][0] * coeff[1][1] -
+ coeff[0][1] * coeff[1][0]) * det;
+
+ *this = inv;
+}
+
+double Matrix::determinant() const
+{
+ double determinant;
+
+ determinant = (coeff[0][0] *
+ (coeff[1][1] * coeff[2][2] -
+ coeff[1][2] * coeff[2][1]));
+ determinant -= (coeff[1][0] *
+ (coeff[0][1] * coeff[2][2] -
+ coeff[0][2] * coeff[2][1]));
+ determinant += (coeff[2][0] *
+ (coeff[0][1] * coeff[1][2] -
+ coeff[0][2] * coeff[1][1]));
+
+ return determinant;
+}
+
+} // namespace DigikamPerspectiveImagesPlugin
diff --git a/src/imageplugins/perspective/matrix.h b/src/imageplugins/perspective/matrix.h
new file mode 100644
index 00000000..fbc5a1aa
--- /dev/null
+++ b/src/imageplugins/perspective/matrix.h
@@ -0,0 +1,106 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a matrix implementation for image
+ * perspective adjustment.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_PERSPECTIVE_MATRIX_H
+#define IMAGEEFFECT_PERSPECTIVE_MATRIX_H
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class Matrix
+{
+public:
+
+ /**
+ * Matrix:
+ *
+ * Initializes matrix to the identity matrix.
+ */
+ Matrix();
+
+ /**
+ * translate:
+ * @x: Translation in X direction.
+ * @y: Translation in Y direction.
+ *
+ * Translates the matrix by x and y.
+ */
+ void translate(double x, double y);
+
+ /**
+ * scale:
+ * @x: X scale factor.
+ * @y: Y scale factor.
+ *
+ * Scales the matrix by x and y
+ */
+ void scale(double x, double y);
+
+ /**
+ * invert:
+ *
+ * Inverts this matrix.
+ */
+ void invert();
+
+ /**
+ * multiply:
+ * @matrix: The other input matrix.
+ *
+ * Multiplies this matrix with another matrix
+ */
+ void multiply(const Matrix &matrix1);
+
+ /**
+ * transformPoint:
+ * @x: The source X coordinate.
+ * @y: The source Y coordinate.
+ * @newx: The transformed X coordinate.
+ * @newy: The transformed Y coordinate.
+ *
+ * Transforms a point in 2D as specified by the transformation matrix.
+ */
+ void transformPoint(double x, double y, double *newx, double *newy) const;
+
+ /**
+ * determinant:
+ *
+ * Calculates the determinant of this matrix.
+ *
+ * Returns: The determinant.
+ */
+ double determinant() const;
+
+ /**
+ * coeff:
+ *
+ * The 3x3 matrix data
+ */
+ double coeff[3][3];
+};
+
+} // namespace DigikamPerspectiveImagesPlugin
+
+#endif // IMAGEEFFECT_PERSPECTIVE_MATRIX_H
diff --git a/src/imageplugins/perspective/perspectivetool.cpp b/src/imageplugins/perspective/perspectivetool.cpp
new file mode 100644
index 00000000..30d0a2cf
--- /dev/null
+++ b/src/imageplugins/perspective/perspectivetool.cpp
@@ -0,0 +1,244 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * 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 <tqcheckbox.h>
+#include <tqframe.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kcolorbutton.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdepopupmenu.h>
+#include <kseparator.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "editortoolsettings.h"
+#include "perspectivewidget.h"
+#include "perspectivetool.h"
+#include "perspectivetool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+PerspectiveTool::PerspectiveTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("perspective");
+ setToolName(i18n("Perspective"));
+ setToolIcon(SmallIcon("perspective"));
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(0);
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* l = new TQVBoxLayout(frame, 5, 0);
+ m_previewWidget = new PerspectiveWidget(525, 350, frame);
+ l->addWidget(m_previewWidget);
+ TQWhatsThis::add(m_previewWidget, i18n("<p>This is the perspective transformation operation preview. "
+ "You can use the mouse for dragging the corner to adjust the "
+ "perspective transformation area."));
+ setToolView(frame);
+
+ // -------------------------------------------------------------
+
+ TQString temp;
+ Digikam::ImageIface iface(0, 0);
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout *gridLayout = new TQGridLayout( m_gboxSettings->plainPage(), 13, 2);
+
+ TQLabel *label1 = new TQLabel(i18n("New width:"), m_gboxSettings->plainPage());
+ m_newWidthLabel = new TQLabel(temp.setNum( iface.originalWidth()) + i18n(" px"), m_gboxSettings->plainPage());
+ m_newWidthLabel->setAlignment( AlignBottom | AlignRight );
+
+ TQLabel *label2 = new TQLabel(i18n("New height:"), m_gboxSettings->plainPage());
+ m_newHeightLabel = new TQLabel(temp.setNum( iface.originalHeight()) + i18n(" px"), m_gboxSettings->plainPage());
+ m_newHeightLabel->setAlignment( AlignBottom | AlignRight );
+
+ // -------------------------------------------------------------
+
+ KSeparator *line = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ TQLabel *angleLabel = new TQLabel(i18n("Angles (in degrees):"), m_gboxSettings->plainPage());
+ TQLabel *label3 = new TQLabel(i18n(" Top left:"), m_gboxSettings->plainPage());
+ m_topLeftAngleLabel = new TQLabel(m_gboxSettings->plainPage());
+ TQLabel *label4 = new TQLabel(i18n(" Top right:"), m_gboxSettings->plainPage());
+ m_topRightAngleLabel = new TQLabel(m_gboxSettings->plainPage());
+ TQLabel *label5 = new TQLabel(i18n(" Bottom left:"), m_gboxSettings->plainPage());
+ m_bottomLeftAngleLabel = new TQLabel(m_gboxSettings->plainPage());
+ TQLabel *label6 = new TQLabel(i18n(" Bottom right:"), m_gboxSettings->plainPage());
+ m_bottomRightAngleLabel = new TQLabel(m_gboxSettings->plainPage());
+
+ // -------------------------------------------------------------
+
+ KSeparator *line2 = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ m_drawWhileMovingCheckBox = new TQCheckBox(i18n("Draw preview while moving"), m_gboxSettings->plainPage());
+ gridLayout->addMultiCellWidget(line2, 8, 8, 0, 2);
+ gridLayout->addMultiCellWidget(m_drawWhileMovingCheckBox, 9, 9, 0, 2);
+
+ m_drawGridCheckBox = new TQCheckBox(i18n("Draw grid"), m_gboxSettings->plainPage());
+
+ // -------------------------------------------------------------
+
+ TQLabel *label7 = new TQLabel(i18n("Guide color:"), m_gboxSettings->plainPage());
+ m_guideColorBt = new KColorButton( TQColor( TQt::red ), m_gboxSettings->plainPage() );
+ TQWhatsThis::add( m_guideColorBt, i18n("<p>Set here the color used to draw guides dashed-lines."));
+ gridLayout->addMultiCellWidget(label7, 11, 11, 0, 0);
+ gridLayout->addMultiCellWidget(m_guideColorBt, 11, 11, 2, 2);
+
+ TQLabel *label8 = new TQLabel(i18n("Guide width:"), m_gboxSettings->plainPage());
+ m_guideSize = new RIntNumInput(m_gboxSettings->plainPage());
+ m_guideSize->input()->setRange(1, 5, 1, false);
+ m_guideSize->setDefaultValue(1);
+ TQWhatsThis::add( m_guideSize, i18n("<p>Set here the width in pixels used to draw guides dashed-lines."));
+
+ gridLayout->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridLayout->addMultiCellWidget(m_newWidthLabel, 0, 0, 1, 2);
+ gridLayout->addMultiCellWidget(label2, 1, 1, 0, 0);
+ gridLayout->addMultiCellWidget(m_newHeightLabel, 1, 1, 1, 2);
+ gridLayout->addMultiCellWidget(line, 2, 2, 0, 2);
+ gridLayout->addMultiCellWidget(angleLabel, 3, 3, 0, 2);
+ gridLayout->addMultiCellWidget(label3, 4, 4, 0, 0);
+ gridLayout->addMultiCellWidget(m_topLeftAngleLabel, 4, 4, 1, 2);
+ gridLayout->addMultiCellWidget(label4, 5, 5, 0, 0);
+ gridLayout->addMultiCellWidget(m_topRightAngleLabel, 5, 5, 1, 2);
+ gridLayout->addMultiCellWidget(label5, 6, 6, 0, 0);
+ gridLayout->addMultiCellWidget(m_bottomLeftAngleLabel, 6, 6, 1, 2);
+ gridLayout->addMultiCellWidget(label6, 7, 7, 0, 0);
+ gridLayout->addMultiCellWidget(m_bottomRightAngleLabel, 7, 7, 1, 2);
+ gridLayout->addMultiCellWidget(m_drawGridCheckBox, 10, 10, 0, 2);
+ gridLayout->addMultiCellWidget(label8, 12, 12, 0, 0);
+ gridLayout->addMultiCellWidget(m_guideSize, 12, 12, 2, 2);
+ gridLayout->setColStretch(1, 10);
+ gridLayout->setRowStretch(13, 10);
+ gridLayout->setMargin(m_gboxSettings->spacingHint());
+ gridLayout->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_previewWidget, TQ_SIGNAL(signalPerspectiveChanged(TQRect, float, float, float, float)),
+ this, TQ_SLOT(slotUpdateInfo(TQRect, float, float, float, float)));
+
+ connect(m_drawWhileMovingCheckBox, TQ_SIGNAL(toggled(bool)),
+ m_previewWidget, TQ_SLOT(slotToggleDrawWhileMoving(bool)));
+
+ connect(m_drawGridCheckBox, TQ_SIGNAL(toggled(bool)),
+ m_previewWidget, TQ_SLOT(slotToggleDrawGrid(bool)));
+
+ connect(m_guideColorBt, TQ_SIGNAL(changed(const TQColor&)),
+ m_previewWidget, TQ_SLOT(slotChangeGuideColor(const TQColor&)));
+
+ connect(m_guideSize, TQ_SIGNAL(valueChanged(int)),
+ m_previewWidget, TQ_SLOT(slotChangeGuideSize(int)));
+}
+
+PerspectiveTool::~PerspectiveTool()
+{
+}
+
+void PerspectiveTool::readSettings()
+{
+ TQColor defaultGuideColor(TQt::red);
+ TDEConfig *config = kapp->config();
+ config->setGroup("perspective Tool");
+ m_drawWhileMovingCheckBox->setChecked(config->readBoolEntry("Draw While Moving", true));
+ m_drawGridCheckBox->setChecked(config->readBoolEntry("Draw Grid", false));
+ m_guideColorBt->setColor(config->readColorEntry("Guide Color", &defaultGuideColor));
+ m_guideSize->setValue(config->readNumEntry("Guide Width", m_guideSize->defaultValue()));
+ m_previewWidget->slotToggleDrawWhileMoving(m_drawWhileMovingCheckBox->isChecked());
+ m_previewWidget->slotToggleDrawGrid(m_drawGridCheckBox->isChecked());
+ m_previewWidget->slotChangeGuideColor(m_guideColorBt->color());
+ m_previewWidget->slotChangeGuideSize(m_guideSize->value());
+}
+
+void PerspectiveTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("perspective Tool");
+ config->writeEntry("Draw While Moving", m_drawWhileMovingCheckBox->isChecked());
+ config->writeEntry("Draw Grid", m_drawGridCheckBox->isChecked());
+ config->writeEntry("Guide Color", m_guideColorBt->color());
+ config->writeEntry("Guide Width", m_guideSize->value());
+ config->sync();
+}
+
+void PerspectiveTool::slotResetSettings()
+{
+ m_previewWidget->reset();
+}
+
+void PerspectiveTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ m_previewWidget->applyPerspectiveAdjustment();
+ kapp->restoreOverrideCursor();
+}
+
+void PerspectiveTool::slotUpdateInfo(TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle)
+{
+ TQString temp;
+ m_newWidthLabel->setText(temp.setNum( newSize.width()) + i18n(" px") );
+ m_newHeightLabel->setText(temp.setNum( newSize.height()) + i18n(" px") );
+
+ m_topLeftAngleLabel->setText(temp.setNum( topLeftAngle, 'f', 1 ));
+ m_topRightAngleLabel->setText(temp.setNum( topRightAngle, 'f', 1 ));
+ m_bottomLeftAngleLabel->setText(temp.setNum( bottomLeftAngle, 'f', 1 ));
+ m_bottomRightAngleLabel->setText(temp.setNum( bottomRightAngle, 'f', 1 ));
+}
+
+} // NameSpace DigikamPerspectiveImagesPlugin
diff --git a/src/imageplugins/perspective/perspectivetool.h b/src/imageplugins/perspective/perspectivetool.h
new file mode 100644
index 00000000..6186712f
--- /dev/null
+++ b/src/imageplugins/perspective/perspectivetool.h
@@ -0,0 +1,100 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective.
+ *
+ * Copyright (C) 2005-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.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_PERSPECTIVE_H
+#define IMAGEEFFECT_PERSPECTIVE_H
+
+// TQt includes.
+
+#include <tqrect.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQLabel;
+class TQCheckBox;
+
+class KColorButton;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+}
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class PerspectiveWidget;
+
+class PerspectiveTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ PerspectiveTool(TQObject* parent);
+ ~PerspectiveTool();
+
+private slots:
+
+ void slotResetSettings();
+ void slotUpdateInfo(TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle);
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+
+private:
+
+ TQLabel *m_newWidthLabel;
+ TQLabel *m_newHeightLabel;
+ TQLabel *m_topLeftAngleLabel;
+ TQLabel *m_topRightAngleLabel;
+ TQLabel *m_bottomLeftAngleLabel;
+ TQLabel *m_bottomRightAngleLabel;
+
+ TQCheckBox *m_drawWhileMovingCheckBox;
+ TQCheckBox *m_drawGridCheckBox;
+
+ KDcrawIface::RIntNumInput *m_guideSize;
+
+ KColorButton *m_guideColorBt;
+
+ PerspectiveWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
+#endif /* IMAGEEFFECT_PERSPECTIVE_H */
diff --git a/src/imageplugins/perspective/perspectivewidget.cpp b/src/imageplugins/perspective/perspectivewidget.cpp
new file mode 100644
index 00000000..ae2c5c03
--- /dev/null
+++ b/src/imageplugins/perspective/perspectivewidget.cpp
@@ -0,0 +1,839 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-18
+ * Description : a widget class to edit perspective.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Matrix3 implementation inspired from gimp 2.0
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <cstdio>
+#include <cstdlib>
+#include <cmath>
+
+// TQt includes.
+
+#include <tqregion.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqbrush.h>
+#include <tqpixmap.h>
+#include <tqimage.h>
+#include <tqpointarray.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdeglobal.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "triangle.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "dimgimagefilters.h"
+#include "perspectivewidget.h"
+#include "perspectivewidget.moc"
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+PerspectiveWidget::PerspectiveWidget(int w, int h, TQWidget *parent)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ setBackgroundMode(TQt::NoBackground);
+ setMinimumSize(w, h);
+ setMouseTracking(true);
+
+ m_drawGrid = false;
+ m_drawWhileMoving = true;
+ m_currentResizing = ResizingNone;
+ m_guideColor = TQt::red;
+ m_guideSize = 1;
+
+ m_iface = new Digikam::ImageIface(w, h);
+ uchar *data = m_iface->setPreviewImageSize(w, h);
+ m_w = m_iface->previewWidth();
+ m_h = m_iface->previewHeight();
+ m_origW = m_iface->originalWidth();
+ m_origH = m_iface->originalHeight();
+ m_previewImage = Digikam::DImg(m_w, m_h, m_iface->previewSixteenBit(), m_iface->previewHasAlpha(), data, false);
+
+ m_pixmap = new TQPixmap(w, h);
+
+ m_rect = TQRect(w/2-m_w/2, h/2-m_h/2, m_w, m_h);
+ m_grid = TQPointArray(60);
+
+ reset();
+}
+
+PerspectiveWidget::~PerspectiveWidget()
+{
+ delete m_iface;
+ delete m_pixmap;
+}
+
+Digikam::ImageIface* PerspectiveWidget::imageIface()
+{
+ return m_iface;
+}
+
+TQPoint PerspectiveWidget::getTopLeftCorner(void)
+{
+ return TQPoint( lroundf((float)(m_topLeftPoint.x()*m_origW) / (float)m_w),
+ lroundf((float)(m_topLeftPoint.y()*m_origH) / (float)m_h));
+}
+
+TQPoint PerspectiveWidget::getTopRightCorner(void)
+{
+ return TQPoint( lroundf((float)(m_topRightPoint.x()*m_origW) / (float)m_w),
+ lroundf((float)(m_topRightPoint.y()*m_origH) / (float)m_h));
+}
+
+TQPoint PerspectiveWidget::getBottomLeftCorner(void)
+{
+ return TQPoint( lroundf((float)(m_bottomLeftPoint.x()*m_origW) / (float)m_w),
+ lroundf((float)(m_bottomLeftPoint.y()*m_origH) / (float)m_h));
+}
+
+TQPoint PerspectiveWidget::getBottomRightCorner(void)
+{
+ return TQPoint( lroundf((float)(m_bottomRightPoint.x()*m_origW) / (float)m_w),
+ lroundf((float)(m_bottomRightPoint.y()*m_origH) / (float)m_h));
+}
+
+TQRect PerspectiveWidget::getTargetSize(void)
+{
+ TQPointArray perspectiveArea;
+
+ perspectiveArea.putPoints( 0, 4,
+ getTopLeftCorner().x(), getTopLeftCorner().y(),
+ getTopRightCorner().x(), getTopRightCorner().y(),
+ getBottomRightCorner().x(), getBottomRightCorner().y(),
+ getBottomLeftCorner().x(), getBottomLeftCorner().y() );
+
+ return perspectiveArea.boundingRect();
+}
+
+float PerspectiveWidget::getAngleTopLeft(void)
+{
+ Triangle topLeft(getTopLeftCorner(), getTopRightCorner(), getBottomLeftCorner());
+ return topLeft.angleBAC();
+}
+
+float PerspectiveWidget::getAngleTopRight(void)
+{
+ Triangle topLeft(getTopRightCorner(), getBottomRightCorner(), getTopLeftCorner());
+ return topLeft.angleBAC();
+}
+
+float PerspectiveWidget::getAngleBottomLeft(void)
+{
+ Triangle topLeft(getBottomLeftCorner(), getTopLeftCorner(), getBottomRightCorner());
+ return topLeft.angleBAC();
+}
+
+float PerspectiveWidget::getAngleBottomRight(void)
+{
+ Triangle topLeft(getBottomRightCorner(), getBottomLeftCorner(), getTopRightCorner());
+ return topLeft.angleBAC();
+}
+
+void PerspectiveWidget::reset(void)
+{
+ m_topLeftPoint.setX(0);
+ m_topLeftPoint.setY(0);
+
+ m_topRightPoint.setX(m_w-1);
+ m_topRightPoint.setY(0);
+
+ m_bottomLeftPoint.setX(0);
+ m_bottomLeftPoint.setY(m_h-1);
+
+ m_bottomRightPoint.setX(m_w-1);
+ m_bottomRightPoint.setY(m_h-1);
+
+ m_spot.setX(m_w / 2);
+ m_spot.setY(m_h / 2);
+
+ m_antiAlias = true;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::applyPerspectiveAdjustment(void)
+{
+ Digikam::DImg *orgImage = m_iface->getOriginalImg();
+ Digikam::DImg destImage(orgImage->width(), orgImage->height(), orgImage->sixteenBit(), orgImage->hasAlpha());
+
+ Digikam::DColor background(0, 0, 0, orgImage->hasAlpha() ? 0 : 255, orgImage->sixteenBit());
+
+ // Perform perspective adjustment.
+
+ buildPerspective(TQPoint(0, 0), TQPoint(m_origW, m_origH),
+ getTopLeftCorner(), getTopRightCorner(),
+ getBottomLeftCorner(), getBottomRightCorner(),
+ orgImage, &destImage, background);
+
+ // Perform an auto-croping around the image.
+
+ Digikam::DImg targetImg = destImage.copy(getTargetSize());
+
+ // Update target image.
+ m_iface->putOriginalImage(i18n("Perspective Adjustment"),
+ targetImg.bits(), targetImg.width(), targetImg.height());
+}
+
+void PerspectiveWidget::slotToggleAntiAliasing(bool a)
+{
+ m_antiAlias = a;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::slotToggleDrawWhileMoving(bool draw)
+{
+ m_drawWhileMoving = draw;
+}
+
+void PerspectiveWidget::slotToggleDrawGrid(bool grid)
+{
+ m_drawGrid = grid;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::slotChangeGuideColor(const TQColor &color)
+{
+ m_guideColor = color;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::slotChangeGuideSize(int size)
+{
+ m_guideSize = size;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::updatePixmap(void)
+{
+ m_topLeftCorner.setRect(m_topLeftPoint.x() + m_rect.topLeft().x(),
+ m_topLeftPoint.y() + m_rect.topLeft().y(), 8, 8);
+ m_topRightCorner.setRect(m_topRightPoint.x() - 7 + m_rect.topLeft().x(),
+ m_topRightPoint.y() + m_rect.topLeft().y(), 8, 8);
+ m_bottomLeftCorner.setRect(m_bottomLeftPoint.x() + m_rect.topLeft().x(),
+ m_bottomLeftPoint.y() - 7 + m_rect.topLeft().y(), 8, 8);
+ m_bottomRightCorner.setRect(m_bottomRightPoint.x() - 7 + m_rect.topLeft().x(),
+ m_bottomRightPoint.y() - 7 + m_rect.topLeft().y(), 8, 8);
+
+ // Compute the grid array
+
+ int gXS = m_w / 15;
+ int gYS = m_h / 15;
+
+ for (int i = 0 ; i < 15 ; i++)
+ {
+ int j = i*4;
+
+ //Horizontal line.
+ m_grid.setPoint(j , 0, i*gYS);
+ m_grid.setPoint(j+1, m_w, i*gYS);
+
+ //Vertical line.
+ m_grid.setPoint(j+2, i*gXS, 0);
+ m_grid.setPoint(j+3, i*gXS, m_h);
+ }
+
+ // Draw background
+
+ m_pixmap->fill(colorGroup().background());
+
+ // if we are resizing with the mouse, compute and draw only if drawWhileMoving is set
+ if (m_currentResizing == ResizingNone || m_drawWhileMoving)
+ {
+ // Create preview image
+
+ Digikam::DImg destImage(m_previewImage.width(), m_previewImage.height(),
+ m_previewImage.sixteenBit(), m_previewImage.hasAlpha());
+
+ Digikam::DColor background(colorGroup().background());
+
+ m_transformedCenter = buildPerspective(TQPoint(0, 0), TQPoint(m_w, m_h),
+ m_topLeftPoint, m_topRightPoint,
+ m_bottomLeftPoint, m_bottomRightPoint,
+ &m_previewImage, &destImage, background);
+
+ m_iface->putPreviewImage(destImage.bits());
+
+ // Draw image
+
+ m_iface->paint(m_pixmap, m_rect.x(), m_rect.y(),
+ m_rect.width(), m_rect.height());
+ }
+ else
+ {
+ m_transformedCenter = buildPerspective(TQPoint(0, 0), TQPoint(m_w, m_h),
+ m_topLeftPoint, m_topRightPoint,
+ m_bottomLeftPoint, m_bottomRightPoint);
+ }
+
+ // Drawing selection borders.
+
+ TQPainter p(m_pixmap);
+ p.setPen(TQPen(TQColor(255, 64, 64), 1, TQt::SolidLine));
+ p.drawLine(m_topLeftPoint+m_rect.topLeft(), m_topRightPoint+m_rect.topLeft());
+ p.drawLine(m_topRightPoint+m_rect.topLeft(), m_bottomRightPoint+m_rect.topLeft());
+ p.drawLine(m_bottomRightPoint+m_rect.topLeft(), m_bottomLeftPoint+m_rect.topLeft());
+ p.drawLine(m_bottomLeftPoint+m_rect.topLeft(), m_topLeftPoint+m_rect.topLeft());
+
+ // Drawing selection corners.
+
+ TQBrush brush(TQColor(255, 64, 64));
+ p.fillRect(m_topLeftCorner, brush);
+ p.fillRect(m_topRightCorner, brush);
+ p.fillRect(m_bottomLeftCorner, brush);
+ p.fillRect(m_bottomRightCorner, brush);
+
+ // Drawing the grid.
+
+ if (m_drawGrid)
+ {
+ for (uint i = 0 ; i < m_grid.size() ; i += 4)
+ {
+ //Horizontal line.
+ p.drawLine(m_grid.point(i)+m_rect.topLeft(), m_grid.point(i+1)+m_rect.topLeft());
+
+ //Vertical line.
+ p.drawLine(m_grid.point(i+2)+m_rect.topLeft(), m_grid.point(i+3)+m_rect.topLeft());
+ }
+ }
+
+ // Drawing transformed center.
+
+ p.setPen(TQPen(TQColor(255, 64, 64), 3, TQt::SolidLine));
+ p.drawEllipse( m_transformedCenter.x()+m_rect.topLeft().x()-2,
+ m_transformedCenter.y()+m_rect.topLeft().y()-2, 4, 4 );
+
+ // Drawing vertical and horizontal guide lines.
+
+ int xspot = m_spot.x() + m_rect.x();
+ int yspot = m_spot.y() + m_rect.y();
+ p.setPen(TQPen(TQt::white, m_guideSize, TQt::SolidLine));
+ p.drawLine(xspot, m_rect.top(), xspot, m_rect.bottom());
+ p.drawLine(m_rect.left(), yspot, m_rect.right(), yspot);
+ p.setPen(TQPen(m_guideColor, m_guideSize, TQt::DotLine));
+ p.drawLine(xspot, m_rect.top(), xspot, m_rect.bottom());
+ p.drawLine(m_rect.left(), yspot, m_rect.right(), yspot);
+
+ p.end();
+
+ emit signalPerspectiveChanged(getTargetSize(), getAngleTopLeft(), getAngleTopRight(),
+ getAngleBottomLeft(), getAngleBottomRight());
+}
+
+TQPoint PerspectiveWidget::buildPerspective(TQPoint orignTopLeft, TQPoint orignBottomRight,
+ TQPoint transTopLeft, TQPoint transTopRight,
+ TQPoint transBottomLeft, TQPoint transBottomRight,
+ Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ Digikam::DColor background)
+{
+ Matrix matrix, transform;
+ double scalex;
+ double scaley;
+
+ double x1 = (double)orignTopLeft.x();
+ double y1 = (double)orignTopLeft.y();
+
+ double x2 = (double)orignBottomRight.x();
+ double y2 = (double)orignBottomRight.y();
+
+ double tx1 = (double)transTopLeft.x();
+ double ty1 = (double)transTopLeft.y();
+
+ double tx2 = (double)transTopRight.x();
+ double ty2 = (double)transTopRight.y();
+
+ double tx3 = (double)transBottomLeft.x();
+ double ty3 = (double)transBottomLeft.y();
+
+ double tx4 = (double)transBottomRight.x();
+ double ty4 = (double)transBottomRight.y();
+
+ scalex = scaley = 1.0;
+
+ if ((x2 - x1) > 0)
+ scalex = 1.0 / (double) (x2 - x1);
+
+ if ((y2 - y1) > 0)
+ scaley = 1.0 / (double) (y2 - y1);
+
+ // Determine the perspective transform that maps from
+ // the unit cube to the transformed coordinates
+
+ double dx1, dx2, dx3, dy1, dy2, dy3;
+
+ dx1 = tx2 - tx4;
+ dx2 = tx3 - tx4;
+ dx3 = tx1 - tx2 + tx4 - tx3;
+
+ dy1 = ty2 - ty4;
+ dy2 = ty3 - ty4;
+ dy3 = ty1 - ty2 + ty4 - ty3;
+
+ // Is the mapping affine?
+
+ if ((dx3 == 0.0) && (dy3 == 0.0))
+ {
+ matrix.coeff[0][0] = tx2 - tx1;
+ matrix.coeff[0][1] = tx4 - tx2;
+ matrix.coeff[0][2] = tx1;
+ matrix.coeff[1][0] = ty2 - ty1;
+ matrix.coeff[1][1] = ty4 - ty2;
+ matrix.coeff[1][2] = ty1;
+ matrix.coeff[2][0] = 0.0;
+ matrix.coeff[2][1] = 0.0;
+ }
+ else
+ {
+ double det1, det2;
+
+ det1 = dx3 * dy2 - dy3 * dx2;
+ det2 = dx1 * dy2 - dy1 * dx2;
+
+ if (det1 == 0.0 && det2 == 0.0)
+ matrix.coeff[2][0] = 1.0;
+ else
+ matrix.coeff[2][0] = det1 / det2;
+
+ det1 = dx1 * dy3 - dy1 * dx3;
+
+ if (det1 == 0.0 && det2 == 0.0)
+ matrix.coeff[2][1] = 1.0;
+ else
+ matrix.coeff[2][1] = det1 / det2;
+
+ matrix.coeff[0][0] = tx2 - tx1 + matrix.coeff[2][0] * tx2;
+ matrix.coeff[0][1] = tx3 - tx1 + matrix.coeff[2][1] * tx3;
+ matrix.coeff[0][2] = tx1;
+
+ matrix.coeff[1][0] = ty2 - ty1 + matrix.coeff[2][0] * ty2;
+ matrix.coeff[1][1] = ty3 - ty1 + matrix.coeff[2][1] * ty3;
+ matrix.coeff[1][2] = ty1;
+ }
+
+ matrix.coeff[2][2] = 1.0;
+
+ // transform is initialized to the identity matrix
+ transform.translate(-x1, -y1);
+ transform.scale (scalex, scaley);
+ transform.multiply (matrix);
+
+ // Compute perspective transformation to image if image data containers exist.
+ if (orgImage && destImage)
+ transformAffine(orgImage, destImage, transform, background);
+
+ // Calculate the grid array points.
+ double newX, newY;
+ for (uint i = 0 ; i < m_grid.size() ; i++)
+ {
+ transform.transformPoint(m_grid.point(i).x(), m_grid.point(i).y(), &newX, &newY);
+ m_grid.setPoint(i, lround(newX), lround(newY));
+ }
+
+ // Calculate and return new image center.
+ double newCenterX, newCenterY;
+ transform.transformPoint(x2/2.0, y2/2.0, &newCenterX, &newCenterY);
+
+ return TQPoint(lround(newCenterX), lround(newCenterY));
+}
+
+void PerspectiveWidget::transformAffine(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ const Matrix &matrix, Digikam::DColor background)
+{
+ Matrix m(matrix), inv(matrix);
+
+ int x1, y1, x2, y2; // target bounding box
+ int x, y; // target coordinates
+ int u1, v1, u2, v2; // source bounding box
+ double uinc, vinc, winc; // increments in source coordinates
+ // pr horizontal target coordinate
+
+ double u[5],v[5]; // source coordinates,
+ // 2
+ // / \ 0 is sample in the center of pixel
+ // 1 0 3 1..4 is offset 1 pixel in each
+ // \ / direction (in target space)
+ // 4
+
+ double tu[5],tv[5],tw[5]; // undivided source coordinates and divisor
+
+ uchar *data, *newData;
+ bool sixteenBit;
+ int coords;
+ int width, height;
+ int bytesDepth;
+ int offset;
+ uchar *dest, *d;
+ Digikam::DColor color;
+
+ bytesDepth = orgImage->bytesDepth();
+ data = orgImage->bits();
+ sixteenBit = orgImage->sixteenBit();
+ width = orgImage->width();
+ height = orgImage->height();
+ newData = destImage->bits();
+
+ if (sixteenBit)
+ background.convertToSixteenBit();
+
+ //destImage->fill(background);
+
+ Digikam::DImgImageFilters filters;
+
+ // Find the inverse of the transformation matrix
+ m.invert();
+
+ u1 = 0;
+ v1 = 0;
+ u2 = u1 + width;
+ v2 = v1 + height;
+
+ x1 = u1;
+ y1 = v1;
+ x2 = u2;
+ y2 = v2;
+
+ dest = new uchar[width * bytesDepth];
+
+ uinc = m.coeff[0][0];
+ vinc = m.coeff[1][0];
+ winc = m.coeff[2][0];
+
+ coords = 1;
+
+ // these loops could be rearranged, depending on which bit of code
+ // you'd most like to write more than once.
+
+ for (y = y1; y < y2; y++)
+ {
+ // set up inverse transform steps
+
+ tu[0] = uinc * (x1 + 0.5) + m.coeff[0][1] * (y + 0.5) + m.coeff[0][2] - 0.5;
+ tv[0] = vinc * (x1 + 0.5) + m.coeff[1][1] * (y + 0.5) + m.coeff[1][2] - 0.5;
+ tw[0] = winc * (x1 + 0.5) + m.coeff[2][1] * (y + 0.5) + m.coeff[2][2];
+
+ d = dest;
+
+ for (x = x1; x < x2; x++)
+ {
+ int i; // normalize homogeneous coords
+
+ for (i = 0; i < coords; i++)
+ {
+ if (tw[i] == 1.0)
+ {
+ u[i] = tu[i];
+ v[i] = tv[i];
+ }
+ else if (tw[i] != 0.0)
+ {
+ u[i] = tu[i] / tw[i];
+ v[i] = tv[i] / tw[i];
+ }
+ else
+ {
+ DDebug() << "homogeneous coordinate = 0...\n" << endl;
+ }
+ }
+
+ // Set the destination pixels
+
+ int iu = lround( u [0] );
+ int iv = lround( v [0] );
+
+ if (iu >= u1 && iu < u2 && iv >= v1 && iv < v2)
+ {
+ // u, v coordinates into source
+
+ int u = iu - u1;
+ int v = iv - v1;
+
+ //TODO: Check why antialiasing shows no effect
+ /*if (m_antiAlias)
+ {
+ if (sixteenBit)
+ {
+ unsigned short *d16 = (unsigned short *)d;
+ filters.pixelAntiAliasing16((unsigned short *)data,
+ width, height, u, v, d16+3, d16+2, d16+1, d16);
+ }
+ else
+ {
+ filters.pixelAntiAliasing(data, width, height, u, v,
+ d+3, d+2, d+1, d);
+ }
+ }
+ else
+ {*/
+ offset = (v * width * bytesDepth) + (u * bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(d);
+ //}
+
+ d += bytesDepth;
+ }
+ else // not in source range
+ {
+ // set to background color
+
+ background.setPixel(d);
+ d += bytesDepth;
+ }
+
+ for (i = 0; i < coords; i++)
+ {
+ tu[i] += uinc;
+ tv[i] += vinc;
+ tw[i] += winc;
+ }
+ }
+
+ // set the pixel region row
+
+ offset = (y - y1) * width * bytesDepth;
+ memcpy(newData + offset, dest, width * bytesDepth);
+ }
+
+ delete [] dest;
+}
+
+void PerspectiveWidget::paintEvent( TQPaintEvent * )
+{
+ bitBlt(this, 0, 0, m_pixmap);
+}
+
+void PerspectiveWidget::resizeEvent(TQResizeEvent * e)
+{
+ int old_w = m_w;
+ int old_h = m_h;
+
+ delete m_pixmap;
+ int w = e->size().width();
+ int h = e->size().height();
+ uchar *data = m_iface->setPreviewImageSize(w, h);
+ m_w = m_iface->previewWidth();
+ m_h = m_iface->previewHeight();
+ m_previewImage = Digikam::DImg(m_w, m_h, m_iface->previewSixteenBit(), m_iface->previewHasAlpha(), data, false);
+
+ m_pixmap = new TQPixmap(w, h);
+ TQRect oldRect = m_rect;
+ m_rect = TQRect(w/2-m_w/2, h/2-m_h/2, m_w, m_h);
+
+ float xFactor = (float)m_rect.width()/(float)(oldRect.width());
+ float yFactor = (float)m_rect.height()/(float)(oldRect.height());
+
+ m_topLeftPoint = TQPoint(lroundf(m_topLeftPoint.x()*xFactor),
+ lroundf(m_topLeftPoint.y()*yFactor));
+ m_topRightPoint = TQPoint(lroundf(m_topRightPoint.x()*xFactor),
+ lroundf(m_topRightPoint.y()*yFactor));
+ m_bottomLeftPoint = TQPoint(lroundf(m_bottomLeftPoint.x()*xFactor),
+ lroundf(m_bottomLeftPoint.y()*yFactor));
+ m_bottomRightPoint = TQPoint(lroundf(m_bottomRightPoint.x()*xFactor),
+ lroundf(m_bottomRightPoint.y()*yFactor));
+ m_transformedCenter = TQPoint(lroundf(m_transformedCenter.x()*xFactor),
+ lroundf(m_transformedCenter.y()*yFactor));
+
+ m_spot.setX((int)((float)m_spot.x() * ( (float)m_w / (float)old_w)));
+ m_spot.setY((int)((float)m_spot.y() * ( (float)m_h / (float)old_h)));
+
+ updatePixmap();
+}
+
+void PerspectiveWidget::mousePressEvent ( TQMouseEvent * e )
+{
+ if ( e->button() == TQt::LeftButton &&
+ m_rect.contains( e->x(), e->y() ))
+ {
+ if ( m_topLeftCorner.contains( e->x(), e->y() ) )
+ m_currentResizing = ResizingTopLeft;
+ else if ( m_bottomRightCorner.contains( e->x(), e->y() ) )
+ m_currentResizing = ResizingBottomRight;
+ else if ( m_topRightCorner.contains( e->x(), e->y() ) )
+ m_currentResizing = ResizingTopRight;
+ else if ( m_bottomLeftCorner.contains( e->x(), e->y() ) )
+ m_currentResizing = ResizingBottomLeft;
+ else
+ {
+ m_spot.setX(e->x()-m_rect.x());
+ m_spot.setY(e->y()-m_rect.y());
+ }
+ }
+}
+
+void PerspectiveWidget::mouseReleaseEvent ( TQMouseEvent * e )
+{
+ if ( m_currentResizing != ResizingNone )
+ {
+ unsetCursor();
+ m_currentResizing = ResizingNone;
+
+ // in this case, the pixmap has not been drawn on mouse move
+ if (!m_drawWhileMoving)
+ {
+ updatePixmap();
+ repaint(false);
+ }
+ }
+ else
+ {
+ m_spot.setX(e->x()-m_rect.x());
+ m_spot.setY(e->y()-m_rect.y());
+ updatePixmap();
+ repaint(false);
+ }
+}
+
+void PerspectiveWidget::mouseMoveEvent ( TQMouseEvent * e )
+{
+ if ( e->state() == TQt::LeftButton )
+ {
+ if ( m_currentResizing != ResizingNone )
+ {
+ TQPointArray unsablePoints;
+ TQPoint pm(e->x(), e->y());
+
+ if (!m_rect.contains( pm ))
+ {
+ if (pm.x() > m_rect.right())
+ pm.setX(m_rect.right());
+ else if (pm.x() < m_rect.left())
+ pm.setX(m_rect.left());
+
+ if (pm.y() > m_rect.bottom())
+ pm.setY(m_rect.bottom());
+ else if (pm.y() < m_rect.top())
+ pm.setY(m_rect.top());
+ }
+
+ if ( m_currentResizing == ResizingTopLeft )
+ {
+ unsablePoints.putPoints(0, 7,
+ m_w-1, m_h-1,
+ 0, m_h-1,
+ 0, m_bottomLeftPoint.y()-10,
+ m_bottomLeftPoint.x(), m_bottomLeftPoint.y()-10,
+ m_topRightPoint.x()-10, m_topRightPoint.y(),
+ m_topRightPoint.x()-10, 0,
+ m_w-1, 0 );
+ TQRegion unsableArea(unsablePoints);
+
+ if ( unsableArea.contains(pm) ) return;
+
+ m_topLeftPoint = pm - m_rect.topLeft();
+ setCursor( KCursor::sizeFDiagCursor() );
+ }
+
+ else if ( m_currentResizing == ResizingTopRight )
+ {
+ unsablePoints.putPoints(0, 7,
+ 0, m_h-1,
+ 0, 0,
+ m_topLeftPoint.x()+10, 0,
+ m_topLeftPoint.x()+10, m_topLeftPoint.y(),
+ m_bottomRightPoint.x(), m_bottomRightPoint.y()-10,
+ m_w-1, m_bottomRightPoint.y()-10,
+ m_w-1, m_h-1);
+ TQRegion unsableArea(unsablePoints);
+
+ if ( unsableArea.contains(pm) ) return;
+
+ m_topRightPoint = pm - m_rect.topLeft();
+ setCursor( KCursor::sizeBDiagCursor() );
+ }
+
+ else if ( m_currentResizing == ResizingBottomLeft )
+ {
+ unsablePoints.putPoints(0, 7,
+ m_w-1, 0,
+ m_w-1, m_h-1,
+ m_bottomRightPoint.x()-10, m_h-1,
+ m_bottomRightPoint.x()-10, m_bottomRightPoint.y()+10,
+ m_topLeftPoint.x(), m_topLeftPoint.y()+10,
+ 0, m_topLeftPoint.y(),
+ 0, 0);
+ TQRegion unsableArea(unsablePoints);
+
+ if ( unsableArea.contains(pm) ) return;
+
+ m_bottomLeftPoint = pm - m_rect.topLeft();
+ setCursor( KCursor::sizeBDiagCursor() );
+ }
+
+ else if ( m_currentResizing == ResizingBottomRight )
+ {
+ unsablePoints.putPoints(0, 7,
+ 0, 0,
+ m_w-1, 0,
+ m_w-1, m_topRightPoint.y()+10,
+ m_topRightPoint.x(), m_topRightPoint.y()+10,
+ m_bottomLeftPoint.x()+10, m_bottomLeftPoint.y(),
+ m_bottomLeftPoint.x()+10, m_w-1,
+ 0, m_w-1);
+ TQRegion unsableArea(unsablePoints);
+
+ if ( unsableArea.contains(pm) ) return;
+
+ m_bottomRightPoint = pm - m_rect.topLeft();
+ setCursor( KCursor::sizeFDiagCursor() );
+ }
+
+ else
+ {
+ m_spot.setX(e->x()-m_rect.x());
+ m_spot.setY(e->y()-m_rect.y());
+ }
+
+ updatePixmap();
+ repaint(false);
+ }
+ }
+ else
+ {
+ if ( m_topLeftCorner.contains( e->x(), e->y() ) ||
+ m_bottomRightCorner.contains( e->x(), e->y() ) )
+ setCursor( KCursor::sizeFDiagCursor() );
+
+ else if ( m_topRightCorner.contains( e->x(), e->y() ) ||
+ m_bottomLeftCorner.contains( e->x(), e->y() ) )
+ setCursor( KCursor::sizeBDiagCursor() );
+ else
+ unsetCursor();
+ }
+}
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
diff --git a/src/imageplugins/perspective/perspectivewidget.h b/src/imageplugins/perspective/perspectivewidget.h
new file mode 100644
index 00000000..0047c3e8
--- /dev/null
+++ b/src/imageplugins/perspective/perspectivewidget.h
@@ -0,0 +1,172 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-18
+ * Description : a widget class to edit perspective.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef PERSPECTIVEWIDGET_H
+#define PERSPECTIVEWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqpoint.h>
+#include <tqpointarray.h>
+#include <tqcolor.h>
+#include <tqrect.h>
+
+// Digikam includes.
+
+#include "dimg.h"
+
+// Local includes.
+
+#include "matrix.h"
+
+class TQPixmap;
+
+namespace Digikam
+{
+class ImageIface;
+}
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class PerspectiveWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ PerspectiveWidget(int width, int height, TQWidget *parent=0);
+ ~PerspectiveWidget();
+
+ TQRect getTargetSize(void);
+ TQPoint getTopLeftCorner(void);
+ TQPoint getTopRightCorner(void);
+ TQPoint getBottomLeftCorner(void);
+ TQPoint getBottomRightCorner(void);
+ void reset(void);
+
+ float getAngleTopLeft(void);
+ float getAngleTopRight(void);
+ float getAngleBottomLeft(void);
+ float getAngleBottomRight(void);
+
+ void applyPerspectiveAdjustment(void);
+
+ Digikam::ImageIface* imageIface();
+
+public slots:
+
+ void slotToggleAntiAliasing(bool a);
+ void slotToggleDrawWhileMoving(bool draw);
+ void slotToggleDrawGrid(bool grid);
+
+ void slotChangeGuideColor(const TQColor &color);
+ void slotChangeGuideSize(int size);
+
+signals:
+
+ void signalPerspectiveChanged( TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle );
+
+protected:
+
+ void paintEvent( TQPaintEvent *e );
+ void resizeEvent( TQResizeEvent * e );
+ void mousePressEvent ( TQMouseEvent * e );
+ void mouseReleaseEvent ( TQMouseEvent * e );
+ void mouseMoveEvent ( TQMouseEvent * e );
+
+private: // Widget methods.
+
+ void updatePixmap(void);
+
+ void transformAffine(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ const Matrix &matrix, Digikam::DColor background);
+
+ TQPoint buildPerspective(TQPoint orignTopLeft, TQPoint orignBottomRight,
+ TQPoint transTopLeft, TQPoint transTopRight,
+ TQPoint transBottomLeft, TQPoint transBottomRight,
+ Digikam::DImg *orgImage=0, Digikam::DImg *destImage=0,
+ Digikam::DColor background=Digikam::DColor());
+
+private:
+
+ enum ResizingMode
+ {
+ ResizingNone = 0,
+ ResizingTopLeft,
+ ResizingTopRight,
+ ResizingBottomLeft,
+ ResizingBottomRight
+ };
+
+ bool m_antiAlias;
+ bool m_drawWhileMoving;
+ bool m_drawGrid;
+
+ uint *m_data;
+ int m_w;
+ int m_h;
+ int m_origW;
+ int m_origH;
+
+ int m_currentResizing;
+
+ int m_guideSize;
+
+ TQRect m_rect;
+
+ // Tranformed center area for mouse position control.
+
+ TQPoint m_transformedCenter;
+
+ // Draggable local region selection corners.
+
+ TQRect m_topLeftCorner;
+ TQRect m_topRightCorner;
+ TQRect m_bottomLeftCorner;
+ TQRect m_bottomRightCorner;
+
+ TQPoint m_topLeftPoint;
+ TQPoint m_topRightPoint;
+ TQPoint m_bottomLeftPoint;
+ TQPoint m_bottomRightPoint;
+ TQPoint m_spot;
+
+ TQColor m_guideColor;
+
+ // 60 points will be stored to compute a grid of 15x15 lines.
+ TQPointArray m_grid;
+
+ TQPixmap *m_pixmap;
+
+ Digikam::ImageIface *m_iface;
+ Digikam::DImg m_previewImage;
+};
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
+#endif /* PERSPECTIVEWIDGET_H */
diff --git a/src/imageplugins/perspective/triangle.cpp b/src/imageplugins/perspective/triangle.cpp
new file mode 100644
index 00000000..84f80a07
--- /dev/null
+++ b/src/imageplugins/perspective/triangle.cpp
@@ -0,0 +1,65 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-18
+ * Description : triangle geometry calculation class.
+ *
+ * Copyright (C) 2005-2007 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 <cstdio>
+#include <cstdlib>
+#include <cmath>
+
+// Local includes.
+
+#include "triangle.h"
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+Triangle::Triangle(TQPoint A, TQPoint B, TQPoint C)
+{
+ m_a = distanceP2P(B, C);
+ m_b = distanceP2P(A, C);
+ m_c = distanceP2P(A, B);
+}
+
+float Triangle::angleABC(void)
+{
+ return( 57.295779513082 * acos( (m_b*m_b - m_a*m_a - m_c*m_c ) / (-2*m_a*m_c ) ) );
+}
+
+float Triangle::angleACB(void)
+{
+ return( 57.295779513082 * acos( (m_c*m_c - m_a*m_a - m_b*m_b ) / (-2*m_a*m_b ) ) );
+}
+
+float Triangle::angleBAC(void)
+{
+ return( 57.295779513082 * acos( (m_a*m_a - m_b*m_b - m_c*m_c ) / (-2*m_b*m_c ) ) );
+}
+
+float Triangle::distanceP2P(const TQPoint& p1, const TQPoint& p2)
+{
+ return(sqrt( abs( p2.x()-p1.x() ) * abs( p2.x()-p1.x() ) +
+ abs( p2.y()-p1.y() ) * abs( p2.y()-p1.y() ) ));
+}
+
+} // NameSpace DigikamPerspectiveImagesPlugin
diff --git a/src/imageplugins/perspective/triangle.h b/src/imageplugins/perspective/triangle.h
new file mode 100644
index 00000000..27fcc087
--- /dev/null
+++ b/src/imageplugins/perspective/triangle.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-18
+ * Description : triangle geometry calculation class.
+ *
+ * Copyright (C) 2005-2007 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.
+ *
+ * ============================================================ */
+
+#ifndef TRIANGLE_H
+#define TRIANGLE_H
+
+// TQt includes.
+
+#include <tqpoint.h>
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class Triangle
+{
+
+public:
+
+ Triangle(TQPoint A, TQPoint B, TQPoint C);
+ ~Triangle(){};
+
+ float angleABC(void);
+ float angleACB(void);
+ float angleBAC(void);
+
+private:
+
+ float m_a;
+ float m_b;
+ float m_c;
+
+ float distanceP2P(const TQPoint& p1, const TQPoint& p2);
+};
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
+#endif /* TRIANGLE_H */