1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2005-05-25
* Description : Unsharp Mask 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>
#include <cstdlib>
// Local includes.
#include "ddebug.h"
#include "dimg.h"
#include "dcolor.h"
#include "dimgimagefilters.h"
#include "dimggaussianblur.h"
#include "unsharp.h"
namespace DigikamImagesPluginCore
{
UnsharpMask::UnsharpMask(Digikam::DImg *orgImage, QObject *parent, int radius,
double amount, double threshold)
: DImgThreadedFilter(orgImage, parent, "UnsharpMask")
{
m_radius = radius;
m_amount = amount;
m_threshold = threshold;
initFilter();
}
void UnsharpMask::filterImage(void)
{
int progress;
int quantum;
double quantumThreshold;
double value;
Digikam::DColor p;
Digikam::DColor q;
if (m_orgImage.isNull())
{
DWarning() << k_funcinfo << "No image data available!" << endl;
return;
}
Digikam::DImgGaussianBlur(this, m_orgImage, m_destImage, 0, 10, (int)(m_radius));
quantum = m_destImage.sixteenBit() ? 65535 : 255;
quantumThreshold = quantum*m_threshold;
for (uint y = 0 ; !m_cancel && (y < m_destImage.height()) ; y++)
{
for (uint x = 0 ; !m_cancel && (x < m_destImage.width()) ; x++)
{
p = m_orgImage.getPixelColor(x, y);
q = m_destImage.getPixelColor(x, y);
// Red channel.
value = (double)(p.red())-(double)(q.red());
if (fabs(2.0*value) < quantumThreshold)
value = (double)(p.red());
else
value = (double)(p.red()) + value*m_amount;
q.setRed(CLAMP(ROUND(value), 0, quantum));
// Green Channel.
value = (double)(p.green())-(double)(q.green());
if (fabs(2.0*value) < quantumThreshold)
value = (double)(p.green());
else
value = (double)(p.green()) + value*m_amount;
q.setGreen(CLAMP(ROUND(value), 0, quantum));
// Blue Channel.
value = (double)(p.blue())-(double)(q.blue());
if (fabs(2.0*value) < quantumThreshold)
value = (double)(p.blue());
else
value = (double)(p.blue()) + value*m_amount;
q.setBlue(CLAMP(ROUND(value), 0, quantum));
// Alpha Channel.
value = (double)(p.alpha())-(double)(q.alpha());
if (fabs(2.0*value) < quantumThreshold)
value = (double)(p.alpha());
else
value = (double)(p.alpha()) + value*m_amount;
q.setAlpha(CLAMP(ROUND(value), 0, quantum));
m_destImage.setPixelColor(x, y, q);
}
progress = (int)(10.0 + ((double)y * 90.0) / m_destImage.height());
if ( progress%5 == 0 )
postProgress( progress );
}
}
} // NameSpace DigikamImagesPluginCore
|