diff options
Diffstat (limited to 'src/imageplugins/hotpixels/hotpixelfixer.cpp')
-rw-r--r-- | src/imageplugins/hotpixels/hotpixelfixer.cpp | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/src/imageplugins/hotpixels/hotpixelfixer.cpp b/src/imageplugins/hotpixels/hotpixelfixer.cpp new file mode 100644 index 00000000..d29b8525 --- /dev/null +++ b/src/imageplugins/hotpixels/hotpixelfixer.cpp @@ -0,0 +1,302 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2005-03-27 + * Description : Threaded image filter to fix hot pixels + * + * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net> + * + * 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> + +// TQt includes. + +#include <tqcolor.h> +#include <tqregexp.h> +#include <tqstringlist.h> + +// Local includes. + +#include "dimg.h" +#include "ddebug.h" +#include "hotpixelfixer.h" + +#ifdef HAVE_FLOAT_H +#if HAVE_FLOAT_H +# include <float.h> +#endif +#endif + +#ifndef DBL_MIN +# define DBL_MIN 1e-37 +#endif +#ifndef DBL_MAX +# define DBL_MAX 1e37 +#endif + +namespace DigikamHotPixelsImagesPlugin +{ + +HotPixelFixer::HotPixelFixer(Digikam::DImg *orgImage, TQObject *parent, const TQValueList<HotPixel>& hpList, + int interpolationMethod) + : Digikam::DImgThreadedFilter(orgImage, parent, "HotPixels") +{ + m_hpList = hpList; + m_interpolationMethod = interpolationMethod; + mWeightList.clear(); + + initFilter(); +} + +HotPixelFixer::~HotPixelFixer() +{ +} + +void HotPixelFixer::filterImage(void) +{ + TQValueList <HotPixel>::ConstIterator it; + TQValueList <HotPixel>::ConstIterator end(m_hpList.end()); + for (it = m_hpList.begin() ; it != end ; ++it) + { + HotPixel hp = *it; + interpolate(m_orgImage, hp, m_interpolationMethod); + } + + m_destImage = m_orgImage; +} + +// Interpolates a pixel block +void HotPixelFixer::interpolate (Digikam::DImg &img, HotPixel &hp, int method) +{ + const int xPos = hp.x(); + const int yPos = hp.y(); + bool sixtBits = img.sixteenBit(); + + // Interpolate pixel. + switch (method) + { + case AVERAGE_INTERPOLATION: + { + // We implement the bidimendional one first. + // TODO: implement the rest of directions (V & H) here + + //case twodim: + // { + int sum_weight = 0; + double vr=0.0,vg=0.0,vb=0.0; + int x, y; + Digikam::DColor col; + + for (x = xPos; x < xPos+hp.width(); ++x) + { + if (validPoint(img,TQPoint(x,yPos-1))) + { + col=img.getPixelColor(x,yPos-1); + vr += col.red(); + vg += col.green(); + vb += col.blue(); + ++sum_weight; + } + if (validPoint(img,TQPoint(x,yPos+hp.height()))) + { + col=img.getPixelColor(x,yPos+hp.height()); + vr += col.red(); + vg += col.green(); + vb += col.blue(); + ++sum_weight; + } + } + + for (y = yPos; y < hp.height(); ++y) + { + if (validPoint(img,TQPoint(xPos-1,y))) + { + col=img.getPixelColor(xPos,y); + vr += col.red(); + vg += col.green(); + vb += col.blue(); + ++sum_weight; + } + if (validPoint(img,TQPoint(xPos+hp.width(),y))) + { + col=img.getPixelColor(xPos+hp.width(),y); + vr += col.red(); + vg += col.green(); + vb += col.blue(); + ++sum_weight; + } + } + + if (sum_weight > 0) + { + vr /= (double)sum_weight; + vg /= (double)sum_weight; + vb /= (double)sum_weight; + + + for (x = 0; x < hp.width(); ++x) + for (y = 0; y < hp.height(); ++y) + if (validPoint(img,TQPoint(xPos+x,yPos+y))) + { + int alpha=sixtBits ? 65535 : 255; + int ir=(int )round(vr),ig=(int) round(vg),ib=(int) round(vb); + img.setPixelColor(xPos+x,yPos+y,Digikam::DColor(ir,ig,ib,alpha,sixtBits)); + } + } + break; + } //Case average + + case LINEAR_INTERPOLATION: + //(Bi)linear interpolation. + weightPixels (img,hp,LINEAR_INTERPOLATION,TWODIM_DIRECTION,sixtBits ? 65535: 255); + break; + + case QUADRATIC_INTERPOLATION: + // (Bi)quadratic interpolation. + weightPixels (img,hp,QUADRATIC_INTERPOLATION,TWODIM_DIRECTION,sixtBits ? 65535 : 255); + break; + + case CUBIC_INTERPOLATION: + // (Bi)cubic interpolation. + weightPixels (img,hp,CUBIC_INTERPOLATION,TWODIM_DIRECTION,sixtBits ? 65535 : 255); + break; + } //switch +} + +void HotPixelFixer::weightPixels (Digikam::DImg &img, HotPixel &px, int method, Direction dir,int maxComponent) +{ + //TODO: implement direction here too + + for (int iComp = 0; iComp < 3; ++iComp) + { + // Obtain weight data block. + + Weights w; + int polynomeOrder=-1; + + switch (method) + { + case AVERAGE_INTERPOLATION: // Gilles: to prevent warnings from compiler. + break; + case LINEAR_INTERPOLATION: + polynomeOrder=1; + break; + case QUADRATIC_INTERPOLATION: + polynomeOrder=2; + break; + case CUBIC_INTERPOLATION: + polynomeOrder=3; + break; + } + if (polynomeOrder<0) return; + + // In the one-dimensional case, the width must be 1, + // and the size must be stored in height + + w.setWidth(dir == TWODIM_DIRECTION ? px.width() : 1); + w.setHeight(dir == HORIZONTAL_DIRECTION ? px.width() : px.height()); + w.setPolynomeOrder(polynomeOrder); + w.setTwoDim(dir == TWODIM_DIRECTION); + + //TODO: check this, it must not recalculate existing calculated weights + //for now I don't think it is finding the duplicates fine, so it uses + //the previous one always... + + //if (mWeightList.find(w)==mWeightList.end()) + //{ + w.calculateWeights(); + + // mWeightList.append(w); + + //} + + // Calculate weighted pixel sum. + for (int y = 0; y<px.height(); ++y) + { + for (int x = 0; x < px.width(); ++x) + { + if (validPoint (img,TQPoint(px.x()+x,px.y()+y))) + { + double sum_weight = 0.0, v = 0.0; + size_t i; + + for (i = 0; i < w.positions().count(); ++i) + { + // In the one-dimensional case, only the y coordinate is used. + const int xx = px.x()+(dir == VERTICAL_DIRECTION ? x : + dir== HORIZONTAL_DIRECTION ? w.positions()[i].y() : w.positions()[i].x()); + const int yy = px.y()+(dir == HORIZONTAL_DIRECTION ? y : + w.positions()[i].y()); + + if (validPoint (img,TQPoint(xx, yy))) + { + //TODO: check this. I think it is broken + double weight; + if (dir==VERTICAL_DIRECTION) + { + weight = w[i][y][0]; + } + else if (dir==HORIZONTAL_DIRECTION) + { + weight=w[i][0][x]; + } + else + { + weight=w[i][y][x]; + } + + if (iComp==0) v += weight * img.getPixelColor(xx, yy).red(); + else if (iComp==1) v += weight * img.getPixelColor(xx, yy).green(); + else v += weight * img.getPixelColor(xx, yy).blue(); + + sum_weight += weight; + } + } + + Digikam::DColor color=img.getPixelColor(px.x()+x,px.y()+y); + int component; + if (fabs (v) <= DBL_MIN) + component=0; + else if (sum_weight >= DBL_MIN) + { + component=(int) (v/sum_weight); + //Clamp value + if (component<0) component=0; + if (component>maxComponent) component=maxComponent; + } + else if (v >= 0.0) + component=maxComponent; + else + component=0; + + if (iComp==0) color.setRed(component); + else if (iComp==1) color.setGreen(component); + else color.setBlue(component); + + + img.setPixelColor(px.x()+x,px.y()+y,color); + } + } + } + } +} + +} // NameSpace DigikamHotPixelsImagesPlugin |