00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kis_convolution_kernel.h"
00020
00021 #include <math.h>
00022
00023 #include <QImage>
00024 #include <kis_mask_generator.h>
00025
00026 struct KisConvolutionKernel::Private {
00027 qreal offset;
00028 qreal factor;
00029 Matrix<qreal, Dynamic, Dynamic> data;
00030 };
00031
00032 KisConvolutionKernel::KisConvolutionKernel(quint32 _width, quint32 _height, qreal _offset, qreal _factor) : d(new Private)
00033 {
00034 d->offset = _offset;
00035 d->factor = _factor;
00036 setSize(_width, _height);
00037 }
00038
00039 KisConvolutionKernel::~KisConvolutionKernel()
00040 {
00041 delete d;
00042 }
00043
00044 quint32 KisConvolutionKernel::width() const
00045 {
00046 return d->data.cols();
00047 }
00048
00049 quint32 KisConvolutionKernel::height() const
00050 {
00051 return d->data.rows();
00052 }
00053
00054 void KisConvolutionKernel::setSize(quint32 width, quint32 height)
00055 {
00056 d->data.resize(height, width);
00057 }
00058
00059
00060 qreal KisConvolutionKernel::offset() const
00061 {
00062 return d->offset;
00063 }
00064
00065 qreal KisConvolutionKernel::factor() const
00066 {
00067 return d->factor;
00068 }
00069
00070 void KisConvolutionKernel::setFactor(qreal factor)
00071 {
00072 d->factor = factor;
00073 }
00074
00075 Matrix<qreal, Dynamic, Dynamic>& KisConvolutionKernel::data()
00076 {
00077 return d->data;
00078 }
00079
00080 const Matrix<qreal, Dynamic, Dynamic>* KisConvolutionKernel::data() const
00081 {
00082 return &(d->data);
00083 }
00084
00085 KisConvolutionKernelSP KisConvolutionKernel::fromQImage(const QImage& image)
00086 {
00087 KisConvolutionKernelSP kernel = new KisConvolutionKernel(image.width(), image.height(), 0, 0);
00088
00089 Matrix<qreal, Dynamic, Dynamic>& data = kernel->data();
00090
00091 const quint8* itImage = image.bits();
00092 qreal factor = 0;
00093
00094 for (int r = 0; r < image.height(); r++) {
00095 for (int c = 0; c < image.width(); c++, itImage += 4)
00096 {
00097 uint value = 255 - (*itImage + *(itImage + 1) + *(itImage + 2)) / 3;
00098 data(r, c) = value;
00099 factor += value;
00100 }
00101 }
00102
00103 kernel->setFactor(factor);
00104 return kernel;
00105 }
00106
00107 KisConvolutionKernelSP KisConvolutionKernel::fromMaskGenerator(KisMaskGenerator* kmg, double angle)
00108 {
00109 Q_UNUSED(angle);
00110
00111 qint32 width = (int)(kmg->width() + 0.5);
00112 qint32 height = (int)(kmg->height() + 0.5);
00113
00114 KisConvolutionKernelSP kernel = new KisConvolutionKernel(width, height, 0, 0);
00115
00116 double cosa = cos(angle);
00117 double sina = sin(angle);
00118 double xc = 0.5 * width - 0.5;
00119 double yc = 0.5 * height - 0.5;
00120
00121 Matrix<qreal, Dynamic, Dynamic>& data = kernel->data();
00122 qreal factor = 0;
00123
00124
00125 for (int r = 0; r < height; ++r) {
00126 for (int c = 0; c < width; ++c) {
00127 double x_ = (c - xc);
00128 double y_ = (r - yc);
00129 double x = cosa * x_ - sina * y_;
00130 double y = sina * x_ + cosa * y_;
00131
00132 uint value = 255 - kmg->valueAt(x, y);
00133 data(r, c) = value;
00134 factor += value;
00135 }
00136 }
00137 kernel->setFactor(factor);
00138 return kernel;
00139 }
00140
00141 KisConvolutionKernelSP KisConvolutionKernel::fromMatrix(Matrix<qreal, Dynamic, Dynamic> matrix, qreal offset, qreal factor)
00142 {
00143 KisConvolutionKernelSP kernel = new KisConvolutionKernel(matrix.cols(), matrix.rows(), offset, factor);
00144 kernel->data() = matrix;
00145
00146 return kernel;
00147 }
00148
00149
00150
00151
00152 #if 0
00153 double xr = (x );
00154 double yr = (y );
00155 double n = norme(xr * m_xcoef, yr * m_ycoef);
00156 if (n > 1)
00157 {
00158 return 255;
00159 } else
00160 {
00161 double normeFade = norme(xr * m_xfadecoef, yr * m_yfadecoef);
00162 if (normeFade > 1) {
00163 double xle, yle;
00164
00165
00166
00167
00168 if (xr == 0) {
00169 xle = 0;
00170 yle = yr > 0 ? 1 / m_ycoef : -1 / m_ycoef;
00171 } else {
00172 double c = yr / (double)xr;
00173 xle = sqrt(1 / norme(m_xcoef, c * m_ycoef));
00174 xle = xr > 0 ? xle : -xle;
00175 yle = xle * c;
00176 }
00177
00178 double normeFadeLimitE = norme(xle * m_xfadecoef, yle * m_yfadecoef);
00179 return (uchar)(255 *(normeFade - 1) / (normeFadeLimitE - 1));
00180 } else {
00181 return 0;
00182 }
00183 }
00184 #endif
00185
00186 #include "kis_debug.h"
00187
00188 QDebug operator<<(QDebug debug, const KisConvolutionKernel &c)
00189 {
00190 debug.nospace() << "[" << c.width() << "," << c.height() << "]{";
00191 for (unsigned int i = 0; i < c.width(); ++i) {
00192 debug.nospace() << " {";
00193 for (unsigned int j = 0; j < c.height(); ++j) {
00194 debug.nospace() << (*(c.data()))(j, i) << " ";
00195 }
00196 debug.nospace() << " }";
00197 }
00198 debug.nospace() << c.factor() << " " << c.offset() << " }";
00199 return debug.space();
00200 }