diff options
Diffstat (limited to 'src/imageplugins/coreplugin/sharpnesseditor/refocus.cpp')
-rw-r--r-- | src/imageplugins/coreplugin/sharpnesseditor/refocus.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/refocus.cpp b/src/imageplugins/coreplugin/sharpnesseditor/refocus.cpp new file mode 100644 index 00000000..7e99d663 --- /dev/null +++ b/src/imageplugins/coreplugin/sharpnesseditor/refocus.cpp @@ -0,0 +1,199 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2005-05-25 + * Description : Refocus threaded image filter. + * + * 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 <cmath> + +// Local includes. + +#include "ddebug.h" +#include "dimg.h" +#include "dcolor.h" +#include "dimgimagefilters.h" +#include "matrix.h" +#include "refocus.h" + +namespace DigikamImagesPluginCore +{ + +Refocus::Refocus(Digikam::DImg *orgImage, TQObject *parent, int matrixSize, double radius, + double gauss, double correlation, double noise) + : Digikam::DImgThreadedFilter(orgImage, parent, "Refocus") +{ + m_matrixSize = matrixSize; + m_radius = radius; + m_gauss = gauss; + m_correlation = correlation; + m_noise = noise; + initFilter(); +} + +void Refocus::filterImage(void) +{ + refocusImage(m_orgImage.bits(), m_orgImage.width(), m_orgImage.height(), + m_orgImage.sixteenBit(), m_matrixSize, m_radius, m_gauss, + m_correlation, m_noise); +} + +void Refocus::refocusImage(uchar* data, int width, int height, bool sixteenBit, + int matrixSize, double radius, double gauss, + double correlation, double noise) +{ + CMat *matrix=0; + + // Compute matrix + DDebug() << "Refocus::Compute matrix..." << endl; + + CMat circle, gaussian, convolution; + + RefocusMatrix::make_gaussian_convolution (gauss, &gaussian, matrixSize); + RefocusMatrix::make_circle_convolution (radius, &circle, matrixSize); + RefocusMatrix::init_c_mat (&convolution, matrixSize); + RefocusMatrix::convolve_star_mat (&convolution, &gaussian, &circle); + + matrix = RefocusMatrix::compute_g_matrix (&convolution, matrixSize, correlation, noise, 0.0, true); + + RefocusMatrix::finish_c_mat (&convolution); + RefocusMatrix::finish_c_mat (&gaussian); + RefocusMatrix::finish_c_mat (&circle); + + // Apply deconvolution kernel to image. + DDebug() << "Refocus::Apply Matrix to image..." << endl; + convolveImage(data, m_destImage.bits(), width, height, sixteenBit, + matrix->data, 2 * matrixSize + 1); + + // Clean up memory + delete matrix; +} + +void Refocus::convolveImage(uchar *orgData, uchar *destData, int width, int height, + bool sixteenBit, const double *const matrix, int mat_size) +{ + int progress; + unsigned short *orgData16 = (unsigned short *)orgData; + unsigned short *destData16 = (unsigned short *)destData; + + double valRed, valGreen, valBlue; + int x1, y1, x2, y2, index1, index2; + + const int imageSize = width*height; + const int mat_offset = mat_size / 2; + + for (y1 = 0; !m_cancel && (y1 < height); y1++) + { + for (x1 = 0; !m_cancel && (x1 < width); x1++) + { + valRed = valGreen = valBlue = 0.0; + + if (!sixteenBit) // 8 bits image. + { + uchar red, green, blue; + uchar *ptr; + + for (y2 = 0; !m_cancel && (y2 < mat_size); y2++) + { + for (x2 = 0; !m_cancel && (x2 < mat_size); x2++) + { + index1 = width * (y1 + y2 - mat_offset) + + x1 + x2 - mat_offset; + + if ( index1 >= 0 && index1 < imageSize ) + { + ptr = &orgData[index1*4]; + blue = ptr[0]; + green = ptr[1]; + red = ptr[2]; + const double matrixValue = matrix[y2 * mat_size + x2]; + valRed += matrixValue * red; + valGreen += matrixValue * green; + valBlue += matrixValue * blue; + } + } + } + + index2 = y1 * width + x1; + + if (index2 >= 0 && index2 < imageSize) + { + // To get Alpha channel value from original (unchanged) + memcpy (&destData[index2*4], &orgData[index2*4], 4); + ptr = &destData[index2*4]; + + // Overwrite RGB values to destination. + ptr[0] = (uchar) CLAMP (valBlue, 0, 255); + ptr[1] = (uchar) CLAMP (valGreen, 0, 255); + ptr[2] = (uchar) CLAMP (valRed, 0, 255); + } + } + else // 16 bits image. + { + unsigned short red, green, blue; + unsigned short *ptr; + + for (y2 = 0; !m_cancel && (y2 < mat_size); y2++) + { + for (x2 = 0; !m_cancel && (x2 < mat_size); x2++) + { + index1 = width * (y1 + y2 - mat_offset) + + x1 + x2 - mat_offset; + + if ( index1 >= 0 && index1 < imageSize ) + { + ptr = &orgData16[index1*4]; + blue = ptr[0]; + green = ptr[1]; + red = ptr[2]; + const double matrixValue = matrix[y2 * mat_size + x2]; + valRed += matrixValue * red; + valGreen += matrixValue * green; + valBlue += matrixValue * blue; + } + } + } + + index2 = y1 * width + x1; + + if (index2 >= 0 && index2 < imageSize) + { + // To get Alpha channel value from original (unchanged) + memcpy (&destData16[index2*4], &orgData16[index2*4], 8); + ptr = &destData16[index2*4]; + + // Overwrite RGB values to destination. + ptr[0] = (unsigned short) CLAMP (valBlue, 0, 65535); + ptr[1] = (unsigned short) CLAMP (valGreen, 0, 65535); + ptr[2] = (unsigned short) CLAMP (valRed, 0, 65535); + } + } + } + + // Update the progress bar in dialog. + progress = (int)(((double)y1 * 100.0) / height); + if (progress%5 == 0) + postProgress( progress ); + } +} + +} // NameSpace DigikamImagesPluginCore + |