1 /* This file is part of the KDE Project
2    Copyright (C) 2002 Klaas Freitag <freitag@suse.de>
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17    Boston, MA 02110-1301, USA.
18 */
19 
20 #include "kgammatable.h"
21 
22 #include <math.h>
23 
24 #include <qregexp.h>
25 
26 #include <QDebug>
27 
KGammaTable(int gamma,int brightness,int contrast)28 KGammaTable::KGammaTable(int gamma, int brightness, int contrast)
29     : QObject()
30 {
31     mGamma = (gamma < 1) ? 1 : gamma;
32     mBrightness = brightness;
33     mContrast = contrast;
34     init();
35 }
36 
KGammaTable(const KGammaTable & other)37 KGammaTable::KGammaTable(const KGammaTable &other)
38     : QObject()
39 {
40     mGamma = other.mGamma;
41     mBrightness = other.mBrightness;
42     mContrast = other.mContrast;
43     init();
44 }
45 
init()46 void KGammaTable::init()
47 {
48     mDirty = true;
49 }
50 
51 // Adapted from LabeledGamma::calculateGT()
52 // in kdegraphics/libksane/libksane/widgets/labeled_gamma.cpp
53 //
54 // Input values are expected to be:
55 //   brightness     -50 ... +50
56 //   contrast       -50 ... +50
57 //   gamma           30 ... 300 = 0.3 ... 3.0
58 //
calcTable()59 void KGammaTable::calcTable()
60 {
61     if (mGamma < 1.0) {             // impossibly small
62         //qDebug() << "invalid gamma" << mGamma;
63         mDirty = false;                 // pointless, but don't repeat
64         return;
65     }
66 
67     if (mData.isEmpty()) {              // not allocated yet
68         mData.resize(256);              // do it now
69         //qDebug() << "allocated table size" << mData.size();
70     }
71 
72     ////qDebug() << "b=" << mBrightness << "c=" << mContrast << "g=" << mGamma;
73 
74     const double maxval = (KGammaTable::valueRange - 1);
75     double gam = 100.0 / mGamma;
76     double con = (200.0 / (100.0 - mContrast)) - 1;
77     double halfmax = maxval / 2.0;
78     double bri = (mBrightness / halfmax) * maxval;
79     ////qDebug() << "bri=" << bri << "con=" << con << "gam=" << gam;
80 
81     for (int i = 0; i < mData.size(); ++i) {
82         double x = pow(i / maxval, gam) * maxval;   // apply gamma
83         x = (con * (x - halfmax)) + halfmax;    // apply contrast
84         x += bri;                   // apply brightness
85         mData[i] = qRound(qBound(0.0, x, maxval));  // limit value, save in table
86         ////qDebug() << "  " << i << "->" << mData[i];
87     }
88 
89     mDirty = false;                 // table now calculated
90 }
91 
setBrightness(int brightness)92 void KGammaTable::setBrightness(int brightness)     // slot
93 {
94     mBrightness = brightness;
95     mDirty = true;
96     emit tableChanged();
97 }
98 
setContrast(int contrast)99 void KGammaTable::setContrast(int contrast)     // slot
100 {
101     mContrast = contrast;
102     mDirty = true;
103     emit tableChanged();
104 }
105 
setGamma(int gamma)106 void KGammaTable::setGamma(int gamma)           // slot
107 {
108     mGamma = gamma;
109     mDirty = true;
110     emit tableChanged();
111 }
112 
setAll(int gamma,int brightness,int contrast)113 void KGammaTable::setAll(int gamma, int brightness, int contrast)
114 {
115     mGamma = gamma < 1 ? 1 : gamma;
116     mBrightness = brightness;
117     mContrast = contrast;
118 
119     mDirty = true;
120     emit tableChanged();
121 }
122 
getTable(int size)123 const int *KGammaTable::getTable(int size)
124 {
125     if (size > 0 && size != mData.size()) {
126         //qDebug() << "resize from" << mData.size() << "to" << size;
127         mData.resize(size);
128         mDirty = true;
129     }
130 
131     if (mDirty) {
132         calcTable();
133     }
134     return (mData.constData());
135 }
136 
137 // originally done in KScanOption::set(const QByteArray &)
setFromString(const QString & str)138 bool KGammaTable::setFromString(const QString &str)
139 {
140     QRegExp re("(\\d+),(\\d+),(\\d+)");
141     if (!re.exactMatch(str)) {
142         return (false);    // unrecognised format
143     }
144 
145     int g = re.cap(1).toInt();
146     int b = re.cap(2).toInt();
147     int c = re.cap(3).toInt();
148 
149     setAll(g, b, c);
150     return (true);                  // matched and set
151 }
152 
153 // originally done in KScanOption::get()
toString() const154 QString KGammaTable::toString() const
155 {
156     return (QString("%1,%2,%3").arg(mGamma).arg(mBrightness).arg(mContrast));
157 }
158