krita/image

kis_convolution_kernel.cc

Go to the documentation of this file.
00001 /*
00002  *  Copyright (c) 2005,2008 Cyrille Berger <cberger@cberger.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
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 //     dbgImage << ppVar(xc) << ppVar(yc);
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 //             dbgImage << ppVar(x) << ppVar(y) << ppVar(x_) << ppVar(y_) << ppVar( kmg->interpolatedValueAt( x,y) );
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 /*- m_xcenter*/);
00154 double yr = (y /*- m_ycenter*/);
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         // xle stands for x-coordinate limit exterior
00165         // yle stands for y-coordinate limit exterior
00166         // we are computing the coordinate on the external ellipse in order to compute
00167         // the fade value
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         // On the internal limit of the fade area, normeFade is equal to 1
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 }