You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
6.9 KiB
200 lines
6.9 KiB
/* ============================================================
|
|
*
|
|
* 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
|
|
|