Index: digikam/imageplugins/lenscorrection/autocorrection/klensfun.cpp
===================================================================
--- digikam/imageplugins/lenscorrection/autocorrection/klensfun.cpp	(revision 937541)
+++ digikam/imageplugins/lenscorrection/autocorrection/klensfun.cpp	(working copy)
@@ -531,6 +531,7 @@
 
     if ( m_klf->m_filterCCA )
     {
+    	m_orgImage.prepareSubPixelAccess(); // init lanczos kernel
         for (unsigned int y=0; !m_cancel && (y < m_orgImage.height()); y++)
         {
             if (m_lfModifier->ApplySubpixelDistortion(0.0, y, m_orgImage.width(), 1, pos))
@@ -538,11 +539,11 @@
                 float *src = pos;
                 for (unsigned x = 0; !m_cancel && (x < m_destImage.width()); x++)
                 {
-                    Digikam::DColor destPixel;
+                    Digikam::DColor destPixel(0, 0, 0, 0xFFFF, m_destImage.sixteenBit());
 
-                    destPixel.setRed  (m_orgImage.getPixelColor(src[0], src[1]).red()   );
-                    destPixel.setGreen(m_orgImage.getPixelColor(src[2], src[3]).green() );
-                    destPixel.setBlue (m_orgImage.getPixelColor(src[4], src[5]).blue()  );
+                    destPixel.setRed  (m_orgImage.getSubPixelColorFast(src[0], src[1]).red()   );
+                    destPixel.setGreen(m_orgImage.getSubPixelColorFast(src[2], src[3]).green() );
+                    destPixel.setBlue (m_orgImage.getSubPixelColorFast(src[4], src[5]).blue()  );
 
                     m_destImage.setPixelColor(x, y, destPixel);
                     src += 2 * 3;
@@ -602,7 +603,8 @@
 
         // we need a deep copy first
         Digikam::DImg tempImage(m_destImage.width(), m_destImage.height(), m_destImage.sixteenBit(), m_destImage.hasAlpha());
-
+    	m_destImage.prepareSubPixelAccess(); // init lanczos kernel
+    	
         for (unsigned long y=0; !m_cancel && (y < tempImage.height()); y++)
         {
             if (m_lfModifier->ApplyGeometryDistortion(0.0, y, tempImage.width(), 1, pos))
@@ -612,7 +614,7 @@
                 {
                     //qDebug (" ZZ %f %f %i %i", src[0], src[1], (int)src[0], (int)src[1]);
 
-                    tempImage.setPixelColor(x, y, m_destImage.getPixelColor((int)src[0], (int)src[1]));
+                    tempImage.setPixelColor(x, y, m_destImage.getSubPixelColor(src[0], src[1]));
                     src += 2;
                 }
             }
Index: digikam/libs/dimg/dimgprivate.h
===================================================================
--- digikam/libs/dimg/dimgprivate.h	(revision 937541)
+++ digikam/libs/dimg/dimgprivate.h	(working copy)
@@ -37,6 +37,28 @@
 #include "digikam_export.h"
 #include "dshareddata.h"
 
+/* Lanczos kernel is precomputed in a table with this resolution
+ * The value below seems to be enough for HQ upscaling up to eight times
+ */
+#define LANCZOS_TABLE_RES  256
+/* A support of 3 gives an overall sharper looking image, but
+ * it is a) slower b) gives more sharpening artefacts
+ */
+#define LANCZOS_SUPPORT    2
+/* Define this to use a floating-point implementation of Lanczos interpolation.
+ * The integer implementation is a little bit less accurate, but MUCH faster
+ * (even on machines with FPU - ~2.5 times faster on Core2); besides, it will
+ * run a hell lot faster on computers without a FPU (e.g. PDAs).
+ */
+//#define LANCZOS_DATA_FLOAT
+#ifdef LANCZOS_DATA_FLOAT
+#define LANCZOS_DATA_TYPE float
+#define LANCZOS_DATA_ONE 1.0
+#else
+#define LANCZOS_DATA_TYPE int
+#define LANCZOS_DATA_ONE 4096
+#endif
+
 namespace Digikam
 {
 
@@ -50,6 +72,7 @@
         width             = 0;
         height            = 0;
         data              = 0;
+        lanczos_func	  = 0;
         alpha             = false;
         sixteenBit        = false;
         isReadOnly        = false;
@@ -58,6 +81,7 @@
     ~DImgPrivate()
     {
         delete [] data;
+        delete [] lanczos_func;
     }
 
     bool                    null;
@@ -69,7 +93,8 @@
     unsigned int            height;
 
     unsigned char          *data;
-
+    LANCZOS_DATA_TYPE	   *lanczos_func;
+    
     QMap<int, QByteArray>   metaData;
     QMap<QString, QVariant> attributes;
     QMap<QString, QString>  embeddedText;
Index: digikam/libs/dimg/dimg.cpp
===================================================================
--- digikam/libs/dimg/dimg.cpp	(revision 937541)
+++ digikam/libs/dimg/dimg.cpp	(working copy)
@@ -889,7 +889,7 @@
 
 DColor DImg::getPixelColor(uint x, uint y) const
 {
-    if (isNull() || x > width() || y > height())
+    if (isNull() || x >= width() || y >= height())
     {
         kDebug(50003) << "DImg::getPixelColor() : wrong pixel position!" << endl;
         return DColor();
@@ -900,8 +900,209 @@
     return( DColor(data, sixteenBit()) );
 }
 
-void DImg::setPixelColor(uint x, uint y, DColor color)
+void DImg::prepareSubPixelAccess(void)
 {
+	if (m_priv->lanczos_func)
+		return;
+	
+    /* Precompute the Lanczos kernel */
+    LANCZOS_DATA_TYPE *lanczos_func = new LANCZOS_DATA_TYPE[LANCZOS_SUPPORT * LANCZOS_SUPPORT * LANCZOS_TABLE_RES];
+    for (int i = 0; i < LANCZOS_SUPPORT * LANCZOS_SUPPORT * LANCZOS_TABLE_RES; i++)
+        if (i == 0)
+            lanczos_func [i] = LANCZOS_DATA_ONE;
+        else
+        {
+            float d = sqrt (((float)i) / LANCZOS_TABLE_RES);
+            lanczos_func [i] = (LANCZOS_DATA_TYPE)
+                ((LANCZOS_DATA_ONE * LANCZOS_SUPPORT *
+                  sin (M_PI * d) * sin ((M_PI / LANCZOS_SUPPORT) * d)) /
+                 (M_PI * M_PI * d * d));
+        }
+    
+    m_priv->lanczos_func = lanczos_func;
+}
+
+#ifdef LANCZOS_DATA_FLOAT
+static inline int normalizeAndClamp(float norm, int sum, int max)
+{
+	int r = 0;
+	
+	if (norm != 0.0)
+		r = sum / norm;
+	if (r < 0)
+		r = 0;
+	else if (r > max)
+		r = max;
+	return r;
+}
+#else
+static inline int normalizeAndClamp(int norm, int sum, int max)
+{
+	int r = 0;
+	
+	if (norm != 0)
+		r = sum / norm;
+	if (r < 0)
+		r = 0;
+	else if (r > max)
+		r = max;
+	return r;
+}
+
+#endif
+
+DColor DImg::getSubPixelColor(float x, float y) const 
+{
+    if (isNull() || x >= width() || y >= height())
+    {
+        kDebug(50003) << "DImg::getPixelColor() : wrong pixel position!" << endl;
+        return DColor();
+    }
+    
+    const LANCZOS_DATA_TYPE *lanczos_func = m_priv->lanczos_func;
+    if (lanczos_func == 0)
+    	return DColor();
+   
+    Digikam::DColor col(0, 0, 0, 0xFFFF, sixteenBit());
+    
+#ifdef LANCZOS_DATA_FLOAT
+	float xs = ::ceilf  (x) - LANCZOS_SUPPORT;
+	float xe = ::floorf (x) + LANCZOS_SUPPORT;
+	float ys = ::ceilf  (y) - LANCZOS_SUPPORT;
+	float ye = ::floorf (y) + LANCZOS_SUPPORT;
+	if (xs >= 0 && ys >= 0 && xe < width() && ye < height()) {
+		float norm = 0.0;
+		float sumR = 0.0;
+		float sumG = 0.0;
+		float sumB = 0.0;
+
+		float _dx = x - xs;
+		float dy = y - ys;
+		for (; ys <= ye; ys += 1.0, dy -= 1.0)
+		{
+			float xc, dx = _dx;
+			for (xc = xs; xc <= xe; xc += 1.0, dx -= 1.0)
+			{
+				uchar *data = bits() + (int)(xs*bytesDepth()) + (int)(width()*ys*bytesDepth());
+				DColor src = DColor(data, sixteenBit());
+
+				float d = dx * dx + dy * dy;
+				if (d >= LANCZOS_SUPPORT * LANCZOS_SUPPORT)
+					continue;
+
+				d = lanczos_func [(int)(d * LANCZOS_TABLE_RES)];
+				norm += d;
+				sumR += d * src.red();
+				sumG += d * src.green();
+				sumB += d * src.blue();
+			}
+		}
+
+		int max = sixteenBit()? 65535 : 255;
+		col.setRed(normalizeAndClamp(norm, sumR, max));
+		col.setGreen(normalizeAndClamp(norm, sumG, max));
+		col.setBlue(normalizeAndClamp(norm, sumB, max));
+	}
+#else
+	/* Do it in integer arithmetic, it's faster */
+	int xx = (int)x;
+	int yy = (int)y;
+	int xs = xx + 1 - LANCZOS_SUPPORT;
+	int xe = xx     + LANCZOS_SUPPORT;
+	int ys = yy + 1 - LANCZOS_SUPPORT;
+	int ye = yy     + LANCZOS_SUPPORT;
+
+	int norm = 0;
+	int sumR = 0;
+	int sumG = 0;
+	int sumB = 0;
+
+	int _dx = (int)(x * 4096.0) - (xs << 12);
+	int dy = (int)(y * 4096.0) - (ys << 12);
+	for (; ys <= ye; ys++, dy -= 4096)
+	{
+		int xc, dx = _dx;
+		for (xc = xs; xc <= xe; xc++, dx -= 4096)
+		{
+			DColor src(0, 0, 0, 0xFFFF, sixteenBit());
+			if (xc >=0 && ys >=0 && xc < width() && ys < height()) {
+				uchar *data = bits() + xc*bytesDepth() + width()*ys*bytesDepth();
+				src.setColor(data, sixteenBit());
+			}
+
+			int d = (dx * dx + dy * dy) >> 12;
+			if (d >= 4096 * LANCZOS_SUPPORT * LANCZOS_SUPPORT)
+				continue;
+
+			d = lanczos_func [(d * LANCZOS_TABLE_RES) >> 12];
+			norm += d;
+			sumR += d * src.red();
+			sumG += d * src.green();
+			sumB += d * src.blue();
+		}
+	}
+
+	int max = sixteenBit()? 65535 : 255;
+	col.setRed(normalizeAndClamp(norm, sumR, max));
+	col.setGreen(normalizeAndClamp(norm, sumG, max));
+	col.setBlue(normalizeAndClamp(norm, sumB, max));
+#endif
+    return col;
+    
+}
+
+DColor DImg::getSubPixelColorFast(float x, float y) const
+{
+	int xx = (int)x;
+	int yy = (int)y;
+	float d_x = x - (int)x;
+	float d_y = y - (int)y;
+	uchar *data;
+	
+	DColor d00, d01, d10, d11;
+	DColor col;
+
+	data = bits() + xx*bytesDepth() + yy*width()*bytesDepth();
+	d00.setColor(data, sixteenBit());
+	if ((xx+1) < width()) {
+		data = bits() + (xx+1)*bytesDepth() + yy*width()*bytesDepth();
+		d10.setColor(data, sixteenBit());
+	}
+	if ((yy+1) < height()) {
+		data = bits() + xx*bytesDepth() + (yy+1)*width()*bytesDepth();
+		d01.setColor(data, sixteenBit());
+	}
+	if ((xx+1) < width() && (yy+1) < height()) {
+		data = bits() + (xx+1)*bytesDepth() + (yy+1)*width()*bytesDepth();
+		d11.setColor(data, sixteenBit());
+	}
+	
+	d00.multiply(1.0-d_x);
+	d00.multiply(1.0-d_y);
+	
+	d10.multiply(d_x);
+	d10.multiply(1.0-d_y);
+	
+	d01.multiply(1.0-d_x);
+	d01.multiply(d_y);
+	
+	d11.multiply(d_x);
+	d11.multiply(d_y);
+	
+	col.blendAdd(d00);
+	col.blendAdd(d10);
+	col.blendAdd(d01);
+	col.blendAdd(d11);
+	
+	if (sixteenBit())
+		col.blendClamp16();
+	else
+		col.blendClamp8();
+	return col;
+}
+
+void DImg::setPixelColor(uint x, uint y, const DColor& color)
+{
     if (isNull() || x > width() || y > height())
     {
         kDebug(50003) << "DImg::setPixelColor() : wrong pixel position!" << endl;
Index: digikam/libs/dimg/dimg.h
===================================================================
--- digikam/libs/dimg/dimg.h	(revision 937541)
+++ digikam/libs/dimg/dimg.h	(working copy)
@@ -241,8 +241,11 @@
         better use the inline methods from DColor.
     */
     DColor      getPixelColor(uint x, uint y) const;
-    void        setPixelColor(uint x, uint y, DColor color);
-
+    void        setPixelColor(uint x, uint y, const DColor& color);
+    void        prepareSubPixelAccess();
+    DColor		getSubPixelColor(float x, float y) const;
+    DColor		getSubPixelColorFast(float x, float y) const;
+    
     /**
     Return true if the original image file format cannot be saved. 
     This is depending of DImgLoader::save() implementation. For example
Index: digikam/libs/dimg/dcolor.h
===================================================================
--- digikam/libs/dimg/dcolor.h	(revision 937541)
+++ digikam/libs/dimg/dcolor.h	(working copy)
@@ -140,6 +140,7 @@
     inline void blendAdd(const DColor &src);
     inline void blendClamp8();
     inline void blendClamp16();
+    inline void multiply(float factor);
 };
 
 }  // namespace Digikam
Index: digikam/libs/dimg/dcolorblend.h
===================================================================
--- digikam/libs/dimg/dcolorblend.h	(revision 937541)
+++ digikam/libs/dimg/dcolorblend.h	(working copy)
@@ -167,12 +167,20 @@
 
 inline void DColor::blendClamp8()
 {
-    if (0xFF00 & red())   setRed(255);
-    if (0xFF00 & green()) setGreen(255);
-    if (0xFF00 & blue())  setBlue(255);
-    if (0xFF00 & alpha()) setAlpha(255);
+    if (0xFFFFFF00 & red())   setRed(255);
+    if (0xFFFFFF00 & green()) setGreen(255);
+    if (0xFFFFFF00 & blue())  setBlue(255);
+    if (0xFFFFFF00 & alpha()) setAlpha(255);
 }
 
+inline void DColor::multiply(float factor)
+{
+	setRed(red() * factor);
+	setGreen(green() * factor);
+	setBlue(blue() * factor);
+	setAlpha(alpha() * factor);
+}
+
 } // namespace Digikam
 
 #endif  // DCOLORBLEND_H
