diff options
Diffstat (limited to 'src/imageplugins/lensdistortion')
13 files changed, 1651 insertions, 0 deletions
diff --git a/src/imageplugins/lensdistortion/Makefile.am b/src/imageplugins/lensdistortion/Makefile.am new file mode 100644 index 00000000..cd157aa1 --- /dev/null +++ b/src/imageplugins/lensdistortion/Makefile.am @@ -0,0 +1,34 @@ +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_lensdistortion_la_SOURCES = imageplugin_lensdistortion.cpp \ + lensdistortiontool.cpp \ + lensdistortion.cpp pixelaccess.cpp + +digikamimageplugin_lensdistortion_la_LIBADD = $(LIB_TDEPARTS) \ + $(top_builddir)/src/digikam/libdigikam.la + +digikamimageplugin_lensdistortion_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio + +kde_services_DATA = digikamimageplugin_lensdistortion.desktop + +kde_module_LTLIBRARIES = digikamimageplugin_lensdistortion.la + +rcdir = $(kde_datadir)/digikam +rc_DATA = digikamimageplugin_lensdistortion_ui.rc diff --git a/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion.desktop b/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion.desktop new file mode 100644 index 00000000..da529559 --- /dev/null +++ b/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion.desktop @@ -0,0 +1,50 @@ +[Desktop Entry] +Name=ImagePlugin_LensDistortion +Name[bg]=Приставка за снимки - Аберации от обективи +Name[da]=Billedplugin_Linseforvrængning +Name[el]=ΠρόσθετοΕικόνας_ΠαραμόρφωσηΦακών +Name[fi]=Linssivääristymä +Name[hr]=Izobličena leća +Name[it]=PluginImmagini_DistorsioneLenticolare +Name[nl]=Afbeeldingsplugin_Lensafwijking +Name[sr]=Изобличење сочива +Name[sr@Latn]=Izobličenje sočiva +Name[sv]=Insticksprogram för linsförvrängning +Name[tr]=ResimEklentisi_MercekÇarpıtması +Name[xx]=xxImagePlugin_LensDistortionxx +Type=Service +X-TDE-ServiceTypes=Digikam/ImagePlugin +Encoding=UTF-8 +Comment=Spherical aberration image correction plugin for digiKam +Comment[bg]=Приставка на digiKam за корекция на аберации от обективи в снимките +Comment[ca]=Connector pel digiKam per corregir l'aberració esfèrica d'una imatge +Comment[da]=Plugin til korrigering af sfærisk afvigelse for Digikam +Comment[de]=digiKam-Modul zur Reduzierung kugelförmiger Verzerrung durch Linsen +Comment[el]=Πρόσθετο διόρθωσης εικόνας σφαιρικής παρέκκλισης για το digiKam +Comment[es]=Plugin para digiKam para corrección de aberraciones de imagen esféricas +Comment[et]=DigiKami sfäärilise aberratsiooni korrigeerimise plugin +Comment[fa]=وصلۀ اصلاح تصویر انحراف کروی برای digiKam +Comment[fi]=Palloaberraatio (kalansilmävääristymä) +Comment[gl]=Un plugin de digiKam para corrixir a aberrazón esférica da imaxe +Comment[hr]=digiKam dodatak za ispravljanje kružne aberacije +Comment[is]=Íforrit fyrir digiKam sem minnkar hringskekkingu linsu +Comment[it]=Plugin di correzione dell'aberrazione sferica delle immagini per digiKam +Comment[ja]=digiKam 球面収差補正プラグイン +Comment[nds]=digiKam-Moduul för't Richten vun Kugel-Vertarren +Comment[nl]=Digikam-plugin voor het corrigeren van bolvormige afwijkingen +Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਗੋਲਾ ਐਬੱਰੇਸ਼ਨ ਚਿੱਤਰ ਪਰਭਾਵ ਪਲੱਗਇਨ +Comment[pl]=Wtyczka do programu digiKam korygująca aberrację sferyczną +Comment[pt]=Um 'plugin' do digiKam para corrigir a aberração esférica da imagem +Comment[pt_BR]=Um 'plugin' do digiKam para corrigir a aberração esférica da imagem +Comment[ru]=Модуль digiKam коррекции сферических искажений +Comment[sk]=digiKam plugin na korekciu sférickej aberácie šošovky +Comment[sr]=digiKam-ов прикључак за исправљање сферног искривљења слике +Comment[sr@Latn]=digiKam-ov priključak za ispravljanje sfernog iskrivljenja slike +Comment[sv]=Digikam insticksprogram för korrigering av sfärisk avvikelse i bild +Comment[tr]=digiKam için resim küresel sapma düzeltme eklentisi +Comment[uk]=Втулок коректування сферичних спотворень для digiKam +Comment[vi]=Phần bổ sung sửa quang sai hình cầu ảnh cho digiKam +Comment[xx]=xxSpherical aberration image correction plugin for digiKamxx + +X-TDE-Library=digikamimageplugin_lensdistortion +author=Gilles Caulier, caulier dot gilles at gmail dot com diff --git a/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion_ui.rc b/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion_ui.rc new file mode 100644 index 00000000..4705467e --- /dev/null +++ b/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion_ui.rc @@ -0,0 +1,20 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui version="5" name="digikamimageplugin_lensdistortion" > + + <MenuBar> + + <Menu name="Enhance" ><text>Enh&ance</text> + <Action name="imageplugin_lensdistortion" /> + </Menu> + + </MenuBar> + + <ToolBar name="ToolBar" > + <text>Main Toolbar</text> + </ToolBar> + + <ActionProperties> + <Action name="imageplugin_lensdistortion" /> + </ActionProperties> + +</kpartgui> diff --git a/src/imageplugins/lensdistortion/imageeffect_lensdistortion.cpp b/src/imageplugins/lensdistortion/imageeffect_lensdistortion.cpp new file mode 100644 index 00000000..89420a9c --- /dev/null +++ b/src/imageplugins/lensdistortion/imageeffect_lensdistortion.cpp @@ -0,0 +1,317 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-12-27 + * Description : a plugin to reduce lens distorsions to an image. + * + * Copyright (C) 2004-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. + * + * ============================================================ */ + +// C++ include. + +#include <cstring> +#include <cmath> +#include <cstdlib> + +// TQt includes. + +#include <tqlabel.h> +#include <tqwhatsthis.h> +#include <tqlayout.h> +#include <tqpixmap.h> +#include <tqpainter.h> +#include <tqbrush.h> +#include <tqpen.h> + +// KDE includes. + +#include <tdelocale.h> +#include <tdeconfig.h> +#include <tdeaboutdata.h> +#include <kiconloader.h> +#include <tdeapplication.h> +#include <kstandarddirs.h> +#include <knuminput.h> + +// Local includes. + +#include "version.h" +#include "ddebug.h" +#include "imageiface.h" +#include "imagewidget.h" +#include "lensdistortion.h" +#include "imageeffect_lensdistortion.h" +#include "imageeffect_lensdistortion.moc" + +namespace DigikamLensDistortionImagesPlugin +{ + +ImageEffect_LensDistortion::ImageEffect_LensDistortion(TQWidget* parent) + : Digikam::ImageGuideDlg(parent, i18n("Lens Distortion Correction"), + "lensdistortion", false, true, true, + Digikam::ImageGuideWidget::HVGuideMode) +{ + TQString whatsThis; + + TDEAboutData* about = new TDEAboutData("digikam", + I18N_NOOP("Lens Distortion Correction"), + digikam_version, + I18N_NOOP("A digiKam image plugin to reduce spherical aberration caused " + "by a lens to an image."), + TDEAboutData::License_GPL, + "(c) 2004-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"); + + about->addAuthor("David Hodson", I18N_NOOP("Lens distortion correction algorithm."), + "hodsond at acm dot org"); + + setAboutData(about); + + // ------------------------------------------------------------- + + TQWidget *gboxSettings = new TQWidget(plainPage()); + TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 8, 1, spacingHint()); + + m_maskPreviewLabel = new TQLabel( gboxSettings ); + m_maskPreviewLabel->setAlignment ( TQt::AlignHCenter | TQt::AlignVCenter ); + TQWhatsThis::add( m_maskPreviewLabel, i18n("<p>You can see here a thumbnail preview of the distortion correction " + "applied to a cross pattern.") ); + gridSettings->addMultiCellWidget(m_maskPreviewLabel, 0, 0, 0, 1); + + // ------------------------------------------------------------- + + TQLabel *label1 = new TQLabel(i18n("Main:"), gboxSettings); + + m_mainInput = new KDoubleNumInput(gboxSettings); + m_mainInput->setPrecision(1); + m_mainInput->setRange(-100.0, 100.0, 0.1, true); + TQWhatsThis::add( m_mainInput, i18n("<p>This value controls the amount of distortion. Negative values correct lens barrel " + "distortion, while positive values correct lens pincushion distortion.")); + + gridSettings->addMultiCellWidget(label1, 1, 1, 0, 1); + gridSettings->addMultiCellWidget(m_mainInput, 2, 2, 0, 1); + + // ------------------------------------------------------------- + + TQLabel *label2 = new TQLabel(i18n("Edge:"), gboxSettings); + + m_edgeInput = new KDoubleNumInput(gboxSettings); + m_edgeInput->setPrecision(1); + m_edgeInput->setRange(-100.0, 100.0, 0.1, true); + TQWhatsThis::add( m_edgeInput, i18n("<p>This value controls in the same manner as the Main control, but has more effect " + "at the edges of the image than at the center.")); + + gridSettings->addMultiCellWidget(label2, 3, 3, 0, 1); + gridSettings->addMultiCellWidget(m_edgeInput, 4, 4, 0, 1); + + // ------------------------------------------------------------- + + TQLabel *label3 = new TQLabel(i18n("Zoom:"), gboxSettings); + + m_rescaleInput = new KDoubleNumInput(gboxSettings); + m_rescaleInput->setPrecision(1); + m_rescaleInput->setRange(-100.0, 100.0, 0.1, true); + TQWhatsThis::add( m_rescaleInput, i18n("<p>This value rescales the overall image size.")); + + gridSettings->addMultiCellWidget(label3, 5, 5, 0, 1); + gridSettings->addMultiCellWidget(m_rescaleInput, 6, 6, 0, 1); + + // ------------------------------------------------------------- + + TQLabel *label4 = new TQLabel(i18n("Brighten:"), gboxSettings); + + m_brightenInput = new KDoubleNumInput(gboxSettings); + m_brightenInput->setPrecision(1); + m_brightenInput->setRange(-100.0, 100.0, 0.1, true); + TQWhatsThis::add( m_brightenInput, i18n("<p>This value adjusts the brightness in image corners.")); + + gridSettings->addMultiCellWidget(label4, 7, 7, 0, 1); + gridSettings->addMultiCellWidget(m_brightenInput, 8, 8, 0, 1); + + setUserAreaWidget(gboxSettings); + + // ------------------------------------------------------------- + + connect(m_mainInput, TQ_SIGNAL(valueChanged (double)), + this, TQ_SLOT(slotTimer())); + + connect(m_edgeInput, TQ_SIGNAL(valueChanged (double)), + this, TQ_SLOT(slotTimer())); + + connect(m_rescaleInput, TQ_SIGNAL(valueChanged (double)), + this, TQ_SLOT(slotTimer())); + + connect(m_brightenInput, TQ_SIGNAL(valueChanged (double)), + this, TQ_SLOT(slotTimer())); + + // ------------------------------------------------------------- + + /* Calc transform preview. + We would like a checkered area to demonstrate the effect. + We do not have any drawing support in DImg, so we let TQt draw. + First we create a white TQImage. We convert this to a TQPixmap, + on which we can draw. Then we convert back to TQImage, + convert the TQImage to a DImg which we only need to create once, here. + Later, we apply the effect on a copy and convert the DImg to TQPixmap. + Longing for TQt4 where we can paint directly on the TQImage... + */ + + TQImage preview(120, 120, 32); + memset(preview.bits(), 255, preview.numBytes()); + TQPixmap pix (preview); + TQPainter pt(&pix); + pt.setPen( TQPen(TQt::black, 1) ); + pt.fillRect( 0, 0, pix.width(), pix.height(), TQBrush(TQt::black, TQt::CrossPattern) ); + pt.drawRect( 0, 0, pix.width(), pix.height() ); + pt.end(); + TQImage preview2(pix.convertToImage()); + m_previewRasterImage = Digikam::DImg(preview2.width(), preview2.height(), false, false, preview2.bits()); +} + +ImageEffect_LensDistortion::~ImageEffect_LensDistortion() +{ +} + +void ImageEffect_LensDistortion::readUserSettings(void) +{ + TDEConfig *config = kapp->config(); + config->setGroup("lensdistortion Tool Dialog"); + + m_mainInput->blockSignals(true); + m_edgeInput->blockSignals(true); + m_rescaleInput->blockSignals(true); + m_brightenInput->blockSignals(true); + + m_mainInput->setValue(config->readDoubleNumEntry("2nd Order Distortion", 0.0)); + m_edgeInput->setValue(config->readDoubleNumEntry("4th Order Distortion",0.0)); + m_rescaleInput->setValue(config->readDoubleNumEntry("Zoom Factor", 0.0)); + m_brightenInput->setValue(config->readDoubleNumEntry("Brighten", 0.0)); + + m_mainInput->blockSignals(false); + m_edgeInput->blockSignals(false); + m_rescaleInput->blockSignals(false); + m_brightenInput->blockSignals(false); + + slotEffect(); +} + +void ImageEffect_LensDistortion::writeUserSettings(void) +{ + TDEConfig *config = kapp->config(); + config->setGroup("lensdistortion Tool Dialog"); + config->writeEntry("2nd Order Distortion", m_mainInput->value()); + config->writeEntry("4th Order Distortion", m_edgeInput->value()); + config->writeEntry("Zoom Factor", m_rescaleInput->value()); + config->writeEntry("Brighten", m_brightenInput->value()); + config->sync(); +} + +void ImageEffect_LensDistortion::resetValues() +{ + m_mainInput->blockSignals(true); + m_edgeInput->blockSignals(true); + m_rescaleInput->blockSignals(true); + m_brightenInput->blockSignals(true); + + m_mainInput->setValue(0.0); + m_edgeInput->setValue(0.0); + m_rescaleInput->setValue(0.0); + m_brightenInput->setValue(0.0); + + m_mainInput->blockSignals(false); + m_edgeInput->blockSignals(false); + m_rescaleInput->blockSignals(false); + m_brightenInput->blockSignals(false); +} + +void ImageEffect_LensDistortion::prepareEffect() +{ + m_mainInput->setEnabled(false); + m_edgeInput->setEnabled(false); + m_rescaleInput->setEnabled(false); + m_brightenInput->setEnabled(false); + + double m = m_mainInput->value(); + double e = m_edgeInput->value(); + double r = m_rescaleInput->value(); + double b = m_brightenInput->value(); + + LensDistortion transformPreview(&m_previewRasterImage, 0L, m, e, r, b, 0, 0); + m_maskPreviewLabel->setPixmap(TQPixmap::TQPixmap(transformPreview.getTargetImage().convertToPixmap())); + + Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface(); + + m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>( + new LensDistortion(iface->getOriginalImg(), this, m, e, r, b, 0, 0)); +} + +void ImageEffect_LensDistortion::prepareFinal() +{ + m_mainInput->setEnabled(false); + m_edgeInput->setEnabled(false); + m_rescaleInput->setEnabled(false); + m_brightenInput->setEnabled(false); + + double m = m_mainInput->value(); + double e = m_edgeInput->value(); + double r = m_rescaleInput->value(); + double b = m_brightenInput->value(); + + Digikam::ImageIface iface(0, 0); + + m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>( + new LensDistortion(iface.getOriginalImg(), this, m, e, r, b, 0, 0)); +} + +void ImageEffect_LensDistortion::putPreviewData(void) +{ + Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface(); + + Digikam::DImg imDest = m_threadedFilter->getTargetImage() + .smoothScale(iface->previewWidth(), iface->previewHeight()); + iface->putPreviewImage(imDest.bits()); + + m_imagePreviewWidget->updatePreview(); +} + +void ImageEffect_LensDistortion::putFinalData(void) +{ + Digikam::ImageIface iface(0, 0); + + iface.putOriginalImage(i18n("Lens Distortion"), + m_threadedFilter->getTargetImage().bits()); +} + +void ImageEffect_LensDistortion::renderingFinished() +{ + m_mainInput->setEnabled(true); + m_edgeInput->setEnabled(true); + m_rescaleInput->setEnabled(true); + m_brightenInput->setEnabled(true); +} + +} // NameSpace DigikamLensDistortionImagesPlugin + diff --git a/src/imageplugins/lensdistortion/imageeffect_lensdistortion.h b/src/imageplugins/lensdistortion/imageeffect_lensdistortion.h new file mode 100644 index 00000000..2688a5df --- /dev/null +++ b/src/imageplugins/lensdistortion/imageeffect_lensdistortion.h @@ -0,0 +1,82 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-12-27 + * Description : a plugin to reduce lens distorsions to an image. + * + * Copyright (C) 2004-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. + * + * ============================================================ */ + +#ifndef IMAGEEFFECT_LENSDISTORTION_H +#define IMAGEEFFECT_LENSDISTORTION_H + +// TQt includes. + +#include <tqimage.h> + +// Digikam includes. + +#include "dimg.h" +#include "imageguidedlg.h" + +class TQLabel; + +class KDoubleNumInput; + +namespace DigikamLensDistortionImagesPlugin +{ + +class ImageEffect_LensDistortion : public Digikam::ImageGuideDlg +{ + TQ_OBJECT + + +public: + + ImageEffect_LensDistortion(TQWidget *parent); + ~ImageEffect_LensDistortion(); + +private slots: + + void readUserSettings(); + +private: + + void writeUserSettings(); + void resetValues(); + void prepareEffect(); + void prepareFinal(); + void putPreviewData(); + void putFinalData(); + void renderingFinished(); + +private: + + TQLabel *m_maskPreviewLabel; + + KDoubleNumInput *m_mainInput; + KDoubleNumInput *m_edgeInput; + KDoubleNumInput *m_rescaleInput; + KDoubleNumInput *m_brightenInput; + + Digikam::DImg m_previewRasterImage; +}; + +} // NameSpace DigikamLensDistortionImagesPlugin + +#endif /* IMAGEEFFECT_LENSDISTORTION_H */ diff --git a/src/imageplugins/lensdistortion/imageplugin_lensdistortion.cpp b/src/imageplugins/lensdistortion/imageplugin_lensdistortion.cpp new file mode 100644 index 00000000..73403fa7 --- /dev/null +++ b/src/imageplugins/lensdistortion/imageplugin_lensdistortion.cpp @@ -0,0 +1,69 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-12-27 + * Description : a plugin to reduce lens distorsions to an image. + * + * 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. + * + * ============================================================ */ + +// KDE includes. + +#include <tdelocale.h> +#include <kgenericfactory.h> +#include <klibloader.h> +#include <tdeaction.h> +#include <kcursor.h> + +// Local includes. + +#include "ddebug.h" +#include "lensdistortiontool.h" +#include "imageplugin_lensdistortion.h" +#include "imageplugin_lensdistortion.moc" + +using namespace DigikamLensDistortionImagesPlugin; + +K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_lensdistortion, + KGenericFactory<ImagePlugin_LensDistortion>("digikamimageplugin_lensdistortion")); + +ImagePlugin_LensDistortion::ImagePlugin_LensDistortion(TQObject *parent, const char*, const TQStringList &) + : Digikam::ImagePlugin(parent, "ImagePlugin_LensDistortion") +{ + m_lensdistortionAction = new TDEAction(i18n("Lens Distortion..."), "lensdistortion", 0, + this, TQ_SLOT(slotLensDistortion()), + actionCollection(), "imageplugin_lensdistortion"); + + setXMLFile("digikamimageplugin_lensdistortion_ui.rc"); + + DDebug() << "ImagePlugin_LensDistortion plugin loaded" << endl; +} + +ImagePlugin_LensDistortion::~ImagePlugin_LensDistortion() +{ +} + +void ImagePlugin_LensDistortion::setEnabledActions(bool enable) +{ + m_lensdistortionAction->setEnabled(enable); +} + +void ImagePlugin_LensDistortion::slotLensDistortion() +{ + LensDistortionTool *tool = new LensDistortionTool(this); + loadTool(tool); +} diff --git a/src/imageplugins/lensdistortion/imageplugin_lensdistortion.h b/src/imageplugins/lensdistortion/imageplugin_lensdistortion.h new file mode 100644 index 00000000..ceb24756 --- /dev/null +++ b/src/imageplugins/lensdistortion/imageplugin_lensdistortion.h @@ -0,0 +1,56 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-12-27 + * Description : a plugin to reduce lens distorsions to an image. + * + * 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. + * + * ============================================================ */ + +#ifndef IMAGEPLUGIN_LENSDISTORTION_H +#define IMAGEPLUGIN_LENSDISTORTION_H + +// Digikam includes. + +#include "imageplugin.h" +#include "digikam_export.h" + +class TDEAction; + +class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_LensDistortion : public Digikam::ImagePlugin +{ + TQ_OBJECT + + +public: + + ImagePlugin_LensDistortion(TQObject *parent, const char* name, + const TQStringList &args); + ~ImagePlugin_LensDistortion(); + + void setEnabledActions(bool enable); + +private slots: + + void slotLensDistortion(); + +private: + + TDEAction *m_lensdistortionAction; +}; + +#endif /* IMAGEPLUGIN_LENSDISTORTION_H */ diff --git a/src/imageplugins/lensdistortion/lensdistortion.cpp b/src/imageplugins/lensdistortion/lensdistortion.cpp new file mode 100644 index 00000000..7b18cc93 --- /dev/null +++ b/src/imageplugins/lensdistortion/lensdistortion.cpp @@ -0,0 +1,135 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2005-05-25 + * Description : lens distortion algorithm. + * + * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2001-2003 by David Hodson <hodsond@acm.org> + * + * 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> +#include <cstdlib> + +// Local includes. + +#include "dimg.h" +#include "ddebug.h" +#include "pixelaccess.h" +#include "lensdistortion.h" + +namespace DigikamLensDistortionImagesPlugin +{ + +LensDistortion::LensDistortion(Digikam::DImg *orgImage, TQObject *parent, double main, + double edge, double rescale, double brighten, + int center_x, int center_y) + : Digikam::DImgThreadedFilter(orgImage, parent, "LensDistortion") +{ + m_main = main; + m_edge = edge; + m_rescale = rescale; + m_brighten = brighten; + m_centre_x = center_x; + m_centre_y = center_y; + + initFilter(); +} + +void LensDistortion::filterImage(void) +{ + int Width = m_orgImage.width(); + int Height = m_orgImage.height(); + int bytesDepth = m_orgImage.bytesDepth(); + + uchar *data = m_destImage.bits(); + + // initial copy + + m_destImage.bitBltImage(&m_orgImage, 0, 0); + + // initialize coefficients + + double normallise_radius_sq = 4.0 / (Width * Width + Height * Height); + double center_x = Width * (100.0 + m_centre_x) / 200.0; + double center_y = Height * (100.0 + m_centre_y) / 200.0; + double mult_sq = m_main / 200.0; + double mult_qd = m_edge / 200.0; + double rescale = pow(2.0, - m_rescale / 100.0); + double brighten = - m_brighten / 10.0; + + PixelAccess *pa = new PixelAccess(&m_orgImage); + + /* + * start at image (i, j), increment by (step, step) + * output goes to dst, which is w x h x d in size + * NB: d <= image.bpp + */ + + // We are working on the full image. + int dstWidth = Width; + int dstHeight = Height; + uchar* dst = (uchar*)data; + int step = 1, progress; + + int iLimit, jLimit; + double srcX, srcY, mag; + + iLimit = dstWidth * step; + jLimit = dstHeight * step; + + for (int dstJ = 0 ; !m_cancel && (dstJ < jLimit) ; dstJ += step) + { + for (int dstI = 0 ; !m_cancel && (dstI < iLimit) ; dstI += step) + { + // Get source Coordinates. + double radius_sq; + double off_x; + double off_y; + double radius_mult; + + off_x = dstI - center_x; + off_y = dstJ - center_y; + radius_sq = (off_x * off_x) + (off_y * off_y); + + radius_sq *= normallise_radius_sq; + + radius_mult = radius_sq * mult_sq + radius_sq * radius_sq * mult_qd; + mag = radius_mult; + radius_mult = rescale * (1.0 + radius_mult); + + srcX = center_x + radius_mult * off_x; + srcY = center_y + radius_mult * off_y; + + brighten = 1.0 + mag * brighten; + pa->pixelAccessGetCubic(srcX, srcY, brighten, dst); + dst += bytesDepth; + } + + // Update progress bar in dialog. + + progress = (int) (((double)dstJ * 100.0) / jLimit); + if (m_parent && progress%5 == 0) + postProgress(progress); + } + + delete pa; +} + +} // NameSpace DigikamLensDistortionImagesPlugin diff --git a/src/imageplugins/lensdistortion/lensdistortion.h b/src/imageplugins/lensdistortion/lensdistortion.h new file mode 100644 index 00000000..cbc46105 --- /dev/null +++ b/src/imageplugins/lensdistortion/lensdistortion.h @@ -0,0 +1,63 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2005-05-25 + * Description : lens distortion algorithm. + * + * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2001-2003 by David Hodson <hodsond@acm.org> + * + * 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 LENS_DISTORTION_H +#define LENS_DISTORTION_H + +// Digikam includes. + +#include "dimgthreadedfilter.h" + +namespace DigikamLensDistortionImagesPlugin +{ + +class LensDistortion : public Digikam::DImgThreadedFilter +{ + +public: + + LensDistortion(Digikam::DImg *orgImage, TQObject *parent=0, double main=0.0, + double edge=0.0, double rescale=0.0, double brighten=0.0, + int center_x=0, int center_y=0); + + ~LensDistortion(){}; + +private: + + virtual void filterImage(void); + +private: + + int m_centre_x; + int m_centre_y; + + double m_main; + double m_edge; + double m_rescale; + double m_brighten; +}; + +} // NameSpace DigikamLensDistortionImagesPlugin + +#endif /* LENS_DISTORTION_H */ diff --git a/src/imageplugins/lensdistortion/lensdistortiontool.cpp b/src/imageplugins/lensdistortion/lensdistortiontool.cpp new file mode 100644 index 00000000..8d33e1df --- /dev/null +++ b/src/imageplugins/lensdistortion/lensdistortiontool.cpp @@ -0,0 +1,326 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-12-27 + * Description : a plugin to reduce lens distorsions to an image. + * + * Copyright (C) 2004-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. + * + * ============================================================ */ + +// C++ includes. + +#include <cstring> +#include <cmath> +#include <cstdlib> + +// TQt includes. + +#include <tqbrush.h> +#include <tqlabel.h> +#include <tqlayout.h> +#include <tqpainter.h> +#include <tqpen.h> +#include <tqpixmap.h> +#include <tqwhatsthis.h> +#include <tqimage.h> + +// KDE includes. + +#include <tdeaboutdata.h> +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kiconloader.h> +#include <tdelocale.h> +#include <kstandarddirs.h> + +// LibKDcraw includes. + +#include <libkdcraw/rnuminput.h> + +// Local includes. + +#include "daboutdata.h" +#include "ddebug.h" +#include "imageiface.h" +#include "imagewidget.h" +#include "editortoolsettings.h" +#include "lensdistortion.h" +#include "lensdistortiontool.h" +#include "lensdistortiontool.moc" + +using namespace KDcrawIface; +using namespace Digikam; + +namespace DigikamLensDistortionImagesPlugin +{ + +LensDistortionTool::LensDistortionTool(TQObject* parent) + : EditorToolThreaded(parent) +{ + setName("lensdistortion"); + setToolName(i18n("Lens Distortion")); + setToolIcon(SmallIcon("lensdistortion")); + + m_previewWidget = new ImageWidget("lensdistortion Tool", 0, TQString(), + false, ImageGuideWidget::HVGuideMode); + + setToolView(m_previewWidget); + + // ------------------------------------------------------------- + + m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default| + EditorToolSettings::Ok| + EditorToolSettings::Cancel, + EditorToolSettings::ColorGuide); + TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 9, 1); + + m_maskPreviewLabel = new TQLabel( m_gboxSettings->plainPage() ); + m_maskPreviewLabel->setAlignment ( TQt::AlignHCenter | TQt::AlignVCenter ); + TQWhatsThis::add( m_maskPreviewLabel, i18n("<p>You can see here a thumbnail preview of the distortion correction " + "applied to a cross pattern.") ); + + // ------------------------------------------------------------- + + TQLabel *label1 = new TQLabel(i18n("Main:"), m_gboxSettings->plainPage()); + + m_mainInput = new RDoubleNumInput(m_gboxSettings->plainPage()); + m_mainInput->setPrecision(1); + m_mainInput->setRange(-100.0, 100.0, 0.1); + m_mainInput->setDefaultValue(0.0); + TQWhatsThis::add(m_mainInput, i18n("<p>This value controls the amount of distortion. Negative values correct lens barrel " + "distortion, while positive values correct lens pincushion distortion.")); + + // ------------------------------------------------------------- + + TQLabel *label2 = new TQLabel(i18n("Edge:"), m_gboxSettings->plainPage()); + + m_edgeInput = new RDoubleNumInput(m_gboxSettings->plainPage()); + m_edgeInput->setPrecision(1); + m_edgeInput->setRange(-100.0, 100.0, 0.1); + m_edgeInput->setDefaultValue(0.0); + TQWhatsThis::add(m_edgeInput, i18n("<p>This value controls in the same manner as the Main control, but has more effect " + "at the edges of the image than at the center.")); + + // ------------------------------------------------------------- + + TQLabel *label3 = new TQLabel(i18n("Zoom:"), m_gboxSettings->plainPage()); + + m_rescaleInput = new RDoubleNumInput(m_gboxSettings->plainPage()); + m_rescaleInput->setPrecision(1); + m_rescaleInput->setRange(-100.0, 100.0, 0.1); + m_rescaleInput->setDefaultValue(0.0); + TQWhatsThis::add(m_rescaleInput, i18n("<p>This value rescales the overall image size.")); + + // ------------------------------------------------------------- + + TQLabel *label4 = new TQLabel(i18n("Brighten:"), m_gboxSettings->plainPage()); + + m_brightenInput = new RDoubleNumInput(m_gboxSettings->plainPage()); + m_brightenInput->setPrecision(1); + m_brightenInput->setRange(-100.0, 100.0, 0.1); + m_brightenInput->setDefaultValue(0.0); + TQWhatsThis::add(m_brightenInput, i18n("<p>This value adjusts the brightness in image corners.")); + + grid->addMultiCellWidget(m_maskPreviewLabel, 0, 0, 0, 1); + grid->addMultiCellWidget(label1, 1, 1, 0, 1); + grid->addMultiCellWidget(m_mainInput, 2, 2, 0, 1); + grid->addMultiCellWidget(label2, 3, 3, 0, 1); + grid->addMultiCellWidget(m_edgeInput, 4, 4, 0, 1); + grid->addMultiCellWidget(label3, 5, 5, 0, 1); + grid->addMultiCellWidget(m_rescaleInput, 6, 6, 0, 1); + grid->addMultiCellWidget(label4, 7, 7, 0, 1); + grid->addMultiCellWidget(m_brightenInput, 8, 8, 0, 1); + grid->setRowStretch(9, 10); + grid->setMargin(m_gboxSettings->spacingHint()); + grid->setSpacing(m_gboxSettings->spacingHint()); + + setToolSettings(m_gboxSettings); + init(); + + // ------------------------------------------------------------- + + connect(m_mainInput, TQ_SIGNAL(valueChanged(double)), + this, TQ_SLOT(slotTimer())); + + connect(m_edgeInput, TQ_SIGNAL(valueChanged(double)), + this, TQ_SLOT(slotTimer())); + + connect(m_rescaleInput, TQ_SIGNAL(valueChanged(double)), + this, TQ_SLOT(slotTimer())); + + connect(m_brightenInput, TQ_SIGNAL(valueChanged(double)), + this, TQ_SLOT(slotTimer())); + + connect(m_gboxSettings, TQ_SIGNAL(signalColorGuideChanged()), + this, TQ_SLOT(slotColorGuideChanged())); + + // ------------------------------------------------------------- + + /* Calc transform preview. + We would like a checkered area to demonstrate the effect. + We do not have any drawing support in DImg, so we let TQt draw. + First we create a white TQImage. We convert this to a TQPixmap, + on which we can draw. Then we convert back to TQImage, + convert the TQImage to a DImg which we only need to create once, here. + Later, we apply the effect on a copy and convert the DImg to TQPixmap. + Longing for TQt4 where we can paint directly on the TQImage... + */ + + TQImage preview(120, 120, 32); + memset(preview.bits(), 255, preview.numBytes()); + TQPixmap pix (preview); + TQPainter pt(&pix); + pt.setPen( TQPen(TQt::black, 1) ); + pt.fillRect( 0, 0, pix.width(), pix.height(), TQBrush(TQt::black, TQt::CrossPattern) ); + pt.drawRect( 0, 0, pix.width(), pix.height() ); + pt.end(); + TQImage preview2(pix.convertToImage()); + m_previewRasterImage = DImg(preview2.width(), preview2.height(), false, false, preview2.bits()); +} + +LensDistortionTool::~LensDistortionTool() +{ +} + +void LensDistortionTool::slotColorGuideChanged() +{ + m_previewWidget->slotChangeGuideColor(m_gboxSettings->guideColor()); + m_previewWidget->slotChangeGuideSize(m_gboxSettings->guideSize()); +} + +void LensDistortionTool::readSettings() +{ + TDEConfig *config = kapp->config(); + config->setGroup("lensdistortion Tool"); + + m_mainInput->blockSignals(true); + m_edgeInput->blockSignals(true); + m_rescaleInput->blockSignals(true); + m_brightenInput->blockSignals(true); + + m_mainInput->setValue(config->readDoubleNumEntry("2nd Order Distortion", m_mainInput->defaultValue())); + m_edgeInput->setValue(config->readDoubleNumEntry("4th Order Distortion",m_edgeInput->defaultValue())); + m_rescaleInput->setValue(config->readDoubleNumEntry("Zoom Factor", m_rescaleInput->defaultValue())); + m_brightenInput->setValue(config->readDoubleNumEntry("Brighten", m_brightenInput->defaultValue())); + m_gboxSettings->setGuideColor(config->readColorEntry("Guide Color", &TQt::red)); + m_gboxSettings->setGuideSize(config->readNumEntry("Guide Width", 1)); + + m_mainInput->blockSignals(false); + m_edgeInput->blockSignals(false); + m_rescaleInput->blockSignals(false); + m_brightenInput->blockSignals(false); + + slotColorGuideChanged(); + slotEffect(); +} + +void LensDistortionTool::writeSettings() +{ + TDEConfig *config = kapp->config(); + config->setGroup("lensdistortion Tool"); + config->writeEntry("2nd Order Distortion", m_mainInput->value()); + config->writeEntry("4th Order Distortion", m_edgeInput->value()); + config->writeEntry("Zoom Factor", m_rescaleInput->value()); + config->writeEntry("Brighten", m_brightenInput->value()); + config->writeEntry("Guide Color", m_gboxSettings->guideColor()); + config->writeEntry("Guide Width", m_gboxSettings->guideSize()); + m_previewWidget->writeSettings(); + config->sync(); +} + +void LensDistortionTool::slotResetSettings() +{ + m_mainInput->blockSignals(true); + m_edgeInput->blockSignals(true); + m_rescaleInput->blockSignals(true); + m_brightenInput->blockSignals(true); + + m_mainInput->slotReset(); + m_edgeInput->slotReset(); + m_rescaleInput->slotReset(); + m_brightenInput->slotReset(); + + m_mainInput->blockSignals(false); + m_edgeInput->blockSignals(false); + m_rescaleInput->blockSignals(false); + m_brightenInput->blockSignals(false); +} + +void LensDistortionTool::prepareEffect() +{ + m_mainInput->setEnabled(false); + m_edgeInput->setEnabled(false); + m_rescaleInput->setEnabled(false); + m_brightenInput->setEnabled(false); + + double m = m_mainInput->value(); + double e = m_edgeInput->value(); + double r = m_rescaleInput->value(); + double b = m_brightenInput->value(); + + LensDistortion transformPreview(&m_previewRasterImage, 0L, m, e, r, b, 0, 0); + m_maskPreviewLabel->setPixmap(TQPixmap(transformPreview.getTargetImage().convertToPixmap())); + + ImageIface* iface = m_previewWidget->imageIface(); + + setFilter(dynamic_cast<DImgThreadedFilter*>(new LensDistortion(iface->getOriginalImg(), this, m, e, r, b, 0, 0))); +} + +void LensDistortionTool::prepareFinal() +{ + m_mainInput->setEnabled(false); + m_edgeInput->setEnabled(false); + m_rescaleInput->setEnabled(false); + m_brightenInput->setEnabled(false); + + double m = m_mainInput->value(); + double e = m_edgeInput->value(); + double r = m_rescaleInput->value(); + double b = m_brightenInput->value(); + + ImageIface iface(0, 0); + + setFilter(dynamic_cast<DImgThreadedFilter*>(new LensDistortion(iface.getOriginalImg(), this, m, e, r, b, 0, 0))); +} + +void LensDistortionTool::putPreviewData() +{ + ImageIface* iface = m_previewWidget->imageIface(); + + DImg imDest = filter()->getTargetImage().smoothScale(iface->previewWidth(), iface->previewHeight()); + iface->putPreviewImage(imDest.bits()); + + m_previewWidget->updatePreview(); +} + +void LensDistortionTool::putFinalData() +{ + ImageIface iface(0, 0); + + iface.putOriginalImage(i18n("Lens Distortion"), filter()->getTargetImage().bits()); +} + +void LensDistortionTool::renderingFinished() +{ + m_mainInput->setEnabled(true); + m_edgeInput->setEnabled(true); + m_rescaleInput->setEnabled(true); + m_brightenInput->setEnabled(true); +} + +} // NameSpace DigikamLensDistortionImagesPlugin diff --git a/src/imageplugins/lensdistortion/lensdistortiontool.h b/src/imageplugins/lensdistortion/lensdistortiontool.h new file mode 100644 index 00000000..f3c7b67f --- /dev/null +++ b/src/imageplugins/lensdistortion/lensdistortiontool.h @@ -0,0 +1,92 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-12-27 + * Description : a plugin to reduce lens distorsions to an image. + * + * Copyright (C) 2004-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. + * + * ============================================================ */ + +#ifndef LENSDISTORTIONTOOL_H +#define LENSDISTORTIONTOOL_H + +// Digikam includes. + +#include "dimg.h" +#include "editortool.h" + +class TQLabel; + +namespace KDcrawIface +{ +class RDoubleNumInput; +} + +namespace Digikam +{ +class EditorToolSettings; +class ImageWidget; +} + +namespace DigikamLensDistortionImagesPlugin +{ + +class LensDistortionTool : public Digikam::EditorToolThreaded +{ + TQ_OBJECT + + +public: + + LensDistortionTool(TQObject *parent); + ~LensDistortionTool(); + +private slots: + + void slotResetSettings(); + void slotColorGuideChanged(); + +private: + + void readSettings(); + void writeSettings(); + void prepareEffect(); + void prepareFinal(); + void putPreviewData(); + void putFinalData(); + void renderingFinished(); + +private: + + TQLabel *m_maskPreviewLabel; + + KDcrawIface::RDoubleNumInput *m_mainInput; + KDcrawIface::RDoubleNumInput *m_edgeInput; + KDcrawIface::RDoubleNumInput *m_rescaleInput; + KDcrawIface::RDoubleNumInput *m_brightenInput; + + Digikam::DImg m_previewRasterImage; + + Digikam::ImageWidget *m_previewWidget; + + Digikam::EditorToolSettings *m_gboxSettings; +}; + +} // NameSpace DigikamLensDistortionImagesPlugin + +#endif /* LENSDISTORTIONTOOL_H */ diff --git a/src/imageplugins/lensdistortion/pixelaccess.cpp b/src/imageplugins/lensdistortion/pixelaccess.cpp new file mode 100644 index 00000000..a6041f94 --- /dev/null +++ b/src/imageplugins/lensdistortion/pixelaccess.cpp @@ -0,0 +1,314 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-12-27 + * Description : acess pixels method for lens distortion algorithm. + * + * Copyright (C) 2004-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. + * + * ============================================================ */ + +// C++ includes. + +#include <cstring> +#include <cmath> +#include <cstdlib> + +// Local includes. + +#include "ddebug.h" +#include "pixelaccess.h" + +namespace DigikamLensDistortionImagesPlugin +{ + +PixelAccess::PixelAccess(Digikam::DImg *srcImage) +{ + m_image = srcImage; + + m_width = PixelAccessWidth; + m_height = PixelAccessHeight; + + m_depth = m_image->bytesDepth(); + m_imageWidth = m_image->width(); + m_imageHeight = m_image->height(); + m_sixteenBit = m_image->sixteenBit(); + + for ( int i = 0 ; i < PixelAccessRegions ; i++ ) + { + m_buffer[i] = new Digikam::DImg(m_image->copy(0, 0, m_width, m_height)); + + m_tileMinX[i] = 1; + m_tileMaxX[i] = m_width - 2; + m_tileMinY[i] = 1; + m_tileMaxY[i] = m_height - 2; + } +} + +PixelAccess::~PixelAccess() +{ + for( int i = 0 ; i < PixelAccessRegions ; i++ ) + delete m_buffer[i]; +} + +uchar* PixelAccess::pixelAccessAddress(int i, int j) +{ + return m_buffer[0]->bits() + m_depth * (m_width * (j + 1 - m_tileMinY[0]) + (i + 1 - m_tileMinX[0])); +} + +// Swap region[n] with region[0]. +void PixelAccess::pixelAccessSelectRegion(int n) +{ + Digikam::DImg *temp; + int a, b, c, d; + int i; + + temp = m_buffer[n]; + a = m_tileMinX[n]; + b = m_tileMaxX[n]; + c = m_tileMinY[n]; + d = m_tileMaxY[n]; + + for( i = n ; i > 0 ; i--) + { + m_buffer[i] = m_buffer[i-1]; + m_tileMinX[i] = m_tileMinX[i-1]; + m_tileMaxX[i] = m_tileMaxX[i-1]; + m_tileMinY[i] = m_tileMinY[i-1]; + m_tileMaxY[i] = m_tileMaxY[i-1]; + } + + m_buffer[0] = temp; + m_tileMinX[0] = a; + m_tileMaxX[0] = b; + m_tileMinY[0] = c; + m_tileMaxY[0] = d; +} + +// Buffer[0] is cleared, should start at [i, j], fill rows that overlap image. +void PixelAccess::pixelAccessDoEdge(int i, int j) +{ + int lineStart, lineEnd; + int rowStart, rowEnd; + int lineWidth; + uchar* line; + + lineStart = i; + if (lineStart < 0) lineStart = 0; + lineEnd = i + m_width; + if (lineEnd > m_imageWidth) lineEnd = m_imageWidth; + lineWidth = lineEnd - lineStart; + + if( lineStart >= lineEnd ) + return; + + rowStart = j; + if (rowStart < 0) rowStart = 0; + rowEnd = j + m_height; + if (rowEnd > m_imageHeight) rowEnd = m_imageHeight; + + for( int y = rowStart ; y < rowEnd ; y++ ) + { + line = pixelAccessAddress(lineStart, y); + memcpy(line, m_image->scanLine(y) + lineStart * m_depth, lineWidth * m_depth); + } +} + +// Moves buffer[0] so that [x, y] is inside it. +void PixelAccess::pixelAccessReposition(int xInt, int yInt) +{ + int newStartX = xInt - PixelAccessXOffset; + int newStartY = yInt - PixelAccessYOffset; + + m_tileMinX[0] = newStartX + 1; + m_tileMaxX[0] = newStartX + m_width - 2; + m_tileMinY[0] = newStartY + 1; + m_tileMaxY[0] = newStartY + m_height - 2; + + + if ( (newStartX < 0) || ((newStartX + m_width) >= m_imageWidth) || + (newStartY < 0) || ((newStartY + m_height) >= m_imageHeight) ) + { + // some data is off edge of image + + m_buffer[0]->fill(Digikam::DColor(0,0,0,0, m_sixteenBit)); + + // This could probably be done by bitBltImage but I did not figure out how, + // so leave the working code here. And no, it is not this: + //m_buffer[0]->bitBltImage(m_image, newStartX, newStartY, m_width, m_height, 0, 0); + + if ( ((newStartX + m_width) < 0) || (newStartX >= m_imageWidth) || + ((newStartY + m_height) < 0) || (newStartY >= m_imageHeight) ) + { + // totally outside, just leave it. + } + else + { + pixelAccessDoEdge(newStartX, newStartY); + } + } + else + { + m_buffer[0]->bitBltImage(m_image, newStartX, newStartY, m_width, m_height, 0, 0); + } +} + +void PixelAccess::pixelAccessGetCubic(double srcX, double srcY, double brighten, uchar* dst) +{ + int xInt, yInt; + double dx, dy; + uchar *corner; + + xInt = (int)floor(srcX); + dx = srcX - xInt; + yInt = (int)floor(srcY); + dy = srcY - yInt; + + // We need 4x4 pixels, xInt-1 to xInt+2 horz, yInt-1 to yInt+2 vert + // they're probably in the last place we looked... + + if ((xInt >= m_tileMinX[0]) && (xInt < m_tileMaxX[0]) && + (yInt >= m_tileMinY[0]) && (yInt < m_tileMaxY[0]) ) + { + corner = pixelAccessAddress(xInt - 1, yInt - 1); + cubicInterpolate(corner, m_depth * m_width, dst, m_sixteenBit, dx, dy, brighten); + return; + } + + // Or maybe it was a while back... + + for ( int i = 1 ; i < PixelAccessRegions ; i++) + { + if ((xInt >= m_tileMinX[i]) && (xInt < m_tileMaxX[i]) && + (yInt >= m_tileMinY[i]) && (yInt < m_tileMaxY[i]) ) + { + // Check here first next time + + pixelAccessSelectRegion(i); + corner = pixelAccessAddress(xInt - 1, yInt - 1); + cubicInterpolate(corner, m_depth * m_width, dst, m_sixteenBit, dx, dy, brighten); + return; + } + } + + // Nope, recycle an old region. + + pixelAccessSelectRegion(PixelAccessRegions - 1); + pixelAccessReposition(xInt, yInt); + + corner = pixelAccessAddress(xInt - 1, yInt - 1); + cubicInterpolate(corner, m_depth * m_width, dst, m_sixteenBit, dx, dy, brighten); +} + +/* + * Catmull-Rom cubic interpolation + * + * equally spaced points p0, p1, p2, p3 + * interpolate 0 <= u < 1 between p1 and p2 + * + * (1 u u^2 u^3) ( 0.0 1.0 0.0 0.0 ) (p0) + * ( -0.5 0.0 0.5 0.0 ) (p1) + * ( 1.0 -2.5 2.0 -0.5 ) (p2) + * ( -0.5 1.5 -1.5 0.5 ) (p3) + * + */ +void PixelAccess::cubicInterpolate(uchar* src, int rowStride, uchar* dst, + bool sixteenBit, double dx, double dy, double brighten) +{ + float um1, u, up1, up2; + float vm1, v, vp1, vp2; + int c; + const int numberOfComponents = 4; + float verts[4 * numberOfComponents]; + + um1 = ((-0.5 * dx + 1.0) * dx - 0.5) * dx; + u = (1.5 * dx - 2.5) * dx * dx + 1.0; + up1 = ((-1.5 * dx + 2.0) * dx + 0.5) * dx; + up2 = (0.5 * dx - 0.5) * dx * dx; + + vm1 = ((-0.5 * dy + 1.0) * dy - 0.5) * dy; + v = (1.5 * dy - 2.5) * dy * dy + 1.0; + vp1 = ((-1.5 * dy + 2.0) * dy + 0.5) * dy; + vp2 = (0.5 * dy - 0.5) * dy * dy; + + if (sixteenBit) + { + unsigned short *src16 = (unsigned short *)src; + unsigned short *dst16 = (unsigned short *)dst; + + // for each component, read the values of 4 pixels into array + + for (c = 0 ; c < 4 * numberOfComponents ; c++) + { + verts[c] = vm1 * src16[c] + v * src16[c+rowStride] + vp1 * src16[c+rowStride*2] + vp2 * src16[c+rowStride*3]; + } + + // for each component, compute resulting value from array + + for (c = 0 ; c < numberOfComponents ; c++) + { + float result; + result = um1 * verts[c] + u * verts[c+numberOfComponents] + + up1 * verts[c+numberOfComponents*2] + up2 * verts[c+numberOfComponents*3]; + result *= brighten; + + if (result < 0.0) + { + dst16[c] = 0; + } + else if (result > 65535.0) + { + dst16[c] = 65535; + } + else + { + dst16[c] = (uint)result; + } + } + } + else + { + for (c = 0 ; c < 4 * numberOfComponents ; c++) + { + verts[c] = vm1 * src[c] + v * src[c+rowStride] + vp1 * src[c+rowStride*2] + vp2 * src[c+rowStride*3]; + } + + for (c = 0 ; c < numberOfComponents ; c++) + { + float result; + result = um1 * verts[c] + u * verts[c+numberOfComponents] + + up1 * verts[c+numberOfComponents*2] + up2 * verts[c+numberOfComponents*3]; + result *= brighten; + + if (result < 0.0) + { + dst[c] = 0; + } + else if (result > 255.0) + { + dst[c] = 255; + } + else + { + dst[c] = (uint)result; + } + } + } +} + +} // NameSpace DigikamLensDistortionImagesPlugin + diff --git a/src/imageplugins/lensdistortion/pixelaccess.h b/src/imageplugins/lensdistortion/pixelaccess.h new file mode 100644 index 00000000..734d0779 --- /dev/null +++ b/src/imageplugins/lensdistortion/pixelaccess.h @@ -0,0 +1,93 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-12-27 + * Description : acess pixels method for lens distortion algorithm. + * + * Copyright (C) 2004-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 PIXEL_ACCESS_H +#define PIXEL_ACCESS_H + +#define PixelAccessRegions 20 +#define PixelAccessWidth 40 +#define PixelAccessHeight 20 +#define PixelAccessXOffset 3 +#define PixelAccessYOffset 3 + +// Digikam includes. + +#include "dimg.h" + +namespace DigikamLensDistortionImagesPlugin +{ + + /* PixelAcess class: solving the eternal problem: random, cubic-interpolated, + * sub-pixel coordinate access to an image. + * Assuming that accesses are at least slightly coherent, + * PixelAccess keeps PixelAccessRegions buffers, each containing a + * PixelAccessWidth x PixelAccessHeight region of pixels. + * Buffer[0] is always checked first, so move the last accessed + * region into that position. + * When a request arrives which is outside all the regions, + * get a new region. + * The new region is placed so that the requested pixel is positioned + * at [PixelAccessXOffset, PixelAccessYOffset] in the region. + */ + +class PixelAccess +{ +public: + + PixelAccess(Digikam::DImg *srcImage); + ~PixelAccess(); + + void pixelAccessGetCubic(double srcX, double srcY, double brighten, uchar* dst); + +private: + + Digikam::DImg *m_image; + + //uchar* m_buffer[PixelAccessRegions]; + Digikam::DImg *m_buffer[PixelAccessRegions]; + + int m_width; + int m_height; + int m_depth; + int m_imageWidth; + int m_imageHeight; + bool m_sixteenBit; + int m_tileMinX[PixelAccessRegions]; + int m_tileMaxX[PixelAccessRegions]; + int m_tileMinY[PixelAccessRegions]; + int m_tileMaxY[PixelAccessRegions]; + +protected: + + inline uchar* pixelAccessAddress(int i, int j); + void pixelAccessSelectRegion(int n); + void pixelAccessDoEdge(int i, int j); + void pixelAccessReposition(int xInt, int yInt); + void cubicInterpolate(uchar* src, int rowStride, uchar* dst, + bool sixteenBit, double dx, double dy, double brighten); +}; + +} // NameSpace DigikamLensDistortionImagesPlugin + +#endif /* PIXEL_ACCESS_H */ |