1 /****************************************************************************
2 **
3 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of a Qt Solutions component.
8 **
9 ** Commercial Usage
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Solutions Commercial License Agreement provided
12 ** with the Software or, alternatively, in accordance with the terms
13 ** contained in a written agreement between you and Nokia.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file.  Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file.  Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
35 **
36 ** Please note Third Party Software included with Qt Solutions may impose
37 ** additional restrictions and it is the user's responsibility to ensure
38 ** that they have met the licensing requirements of the GPL, LGPL, or Qt
39 ** Solutions Commercial license and the relevant license of the Third
40 ** Party Software they are using.
41 **
42 ** If you are unsure which license is appropriate for your use, please
43 ** contact Nokia at qt-info@nokia.com.
44 **
45 ****************************************************************************/
46 
47 #include "qtimagefilter.h"
48 #include "convolutionfilter.h"
49 #include "gaussfilter.h"
50 #include "punchfilter.h"
51 #include <QtCore/QMap>
52 #include <QtCore/QByteArray>
53 
createGaussianBlurFilter()54 QtImageFilter *createGaussianBlurFilter()
55 {
56     return reinterpret_cast<QtImageFilter*>(new GaussBlurFilter());
57 }
58 
createDefocusFilter()59 QtImageFilter *createDefocusFilter()
60 {
61 static int kernelmatrix[ 9 ] =
62   { 1,  1, 1,
63     1, -7, 1,
64     1,  1, 1 };
65     auto filter = new ConvolutionFilter();
66     filter->setName(QLatin1String("Defocus"));
67     filter->setDescription(QObject::tr("Blurs the image", "ConvolutionFilter"));
68     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 3, 3), ConvolutionFilter::RGB, ConvolutionFilter::Extend);
69     return reinterpret_cast<QtImageFilter*>(filter);
70 }
71 
createHighlightFilter()72 QtImageFilter *createHighlightFilter()
73 {
74 static int kernelmatrix[ 25 ] =
75   { -1, 0, 0, 0, 0,
76      0, 0, 0, 0, 0,
77      0, 0, 0, 0, 0,
78      0, 0, 0, 0, 0,
79      0, 0, 0, 0, 2 };
80     auto filter = new ConvolutionFilter();
81     filter->setName(QLatin1String("Highlight"));
82     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 5, 5), ConvolutionFilter::RGB, ConvolutionFilter::Extend, 1, 0);
83     return reinterpret_cast<QtImageFilter*>(filter);
84 }
85 
createSharpenFilter()86 QtImageFilter *createSharpenFilter()
87 {
88 static int kernelmatrix[ 25 ] =
89   { -1, -1, -1, -1, -1,
90     -1,  2,  2,  2, -1,
91     -1,  2,  8,  2, -1,
92     -1,  2,  2,  2, -1,
93     -1, -1, -1, -1, -1 };
94     auto filter = new ConvolutionFilter();
95     filter->setName(QLatin1String("Sharpen"));
96     filter->setDescription(QObject::tr("Sharpens the image","ConvolutionFilter"));
97     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 5, 5), ConvolutionFilter::RGB, ConvolutionFilter::Extend, 8, 0);
98     return reinterpret_cast<QtImageFilter*>(filter);
99 }
100 
createSharpenMoreFilter()101 QtImageFilter *createSharpenMoreFilter()
102 {
103 static int kernelmatrix[ 9 ] =
104   { -1, -1, -1,
105     -1,  9, -1,
106     -1, -1, -1 };
107     auto filter = new ConvolutionFilter();
108     filter->setName(QLatin1String("SharpenMore"));
109     filter->setDescription(QObject::tr("Sharpens the image more","ConvolutionFilter"));
110     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 3, 3), ConvolutionFilter::RGB, ConvolutionFilter::Extend, 1, 0);
111     return reinterpret_cast<QtImageFilter*>(filter);
112 }
113 
createSharpenEvenMoreFilter()114 QtImageFilter *createSharpenEvenMoreFilter()
115 {
116 static int kernelmatrix[ 9 ] =
117   { -1, -2, -1,
118     -2, 13, -2,
119     -1, -2, -1 };
120     auto filter = new ConvolutionFilter();
121     filter->setName(QLatin1String("SharpenEvenMore"));
122     filter->setDescription(QObject::tr("Sharpens the image even more","ConvolutionFilter"));
123     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 3, 3), ConvolutionFilter::RGB, ConvolutionFilter::Extend, 1, 0);
124     return reinterpret_cast<QtImageFilter*>(filter);
125 }
126 
createBigEdgeFilter()127 QtImageFilter *createBigEdgeFilter()
128 {
129 static int kernelmatrix[ 25 ] =
130   { -2, -2, -2, -2, -2,
131     -2, -3, -3, -3, -2,
132     -2, -3, 53, -3, -2,
133     -2, -3, -3, -3, -2,
134     -2, -2, -2, -2, -2 };
135     auto filter = new ConvolutionFilter();
136     filter->setName(QLatin1String("BigEdge"));
137     filter->setDescription(QObject::tr("Creates big edges","ConvolutionFilter"));
138     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 5, 5), ConvolutionFilter::RGB, ConvolutionFilter::Extend, 1, 0);
139     return reinterpret_cast<QtImageFilter*>(filter);
140 }
141 
createEmbossFilter()142 QtImageFilter *createEmbossFilter()
143 {
144 static int kernelmatrix[ 9 ] =
145   { -1, -1,  0,
146     -1,  0,  1,
147      0,  1,  1 };
148     auto filter = new ConvolutionFilter();
149     filter->setName(QLatin1String("Emboss"));
150     filter->setDescription(QObject::tr("Creates an emboss effect on the image, resulting in a greyish image","ConvolutionFilter"));
151     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 3, 3), ConvolutionFilter::RGB, ConvolutionFilter::Extend, 1, 128);
152     return reinterpret_cast<QtImageFilter*>(filter);
153 }
154 
createEmbossColorFilter()155 QtImageFilter *createEmbossColorFilter()
156 {
157 static int kernelmatrix[9] =
158 {   -1, -1,  0,
159     -1,  1,  1,
160      0,  1,  1 };
161     auto filter = new ConvolutionFilter();
162     filter->setName(QLatin1String("EmbossColor"));
163     filter->setDescription(QObject::tr("Creates an emboss effect on the image, while keeping most of the colours","ConvolutionFilter"));
164     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 3, 3), ConvolutionFilter::RGB, ConvolutionFilter::Extend, 1, 0);
165     return reinterpret_cast<QtImageFilter*>(filter);
166 }
167 
createEdgeDetectFilter()168 QtImageFilter *createEdgeDetectFilter()
169 {
170 static int kernelmatrix[ 9 ] =
171   { -5, -2, -5,
172     -5, 39, -5,
173     -5, -5, -5 };
174     auto filter = new ConvolutionFilter();
175     filter->setName(QLatin1String("EdgeDetect"));
176     filter->setDescription(QObject::tr("Creates a filter that enables you to detect edges easily.","ConvolutionFilter"));
177     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 3, 3), ConvolutionFilter::RGB, ConvolutionFilter::Extend, 1, 50);
178     return reinterpret_cast<QtImageFilter*>(filter);
179 }
180 
createNegativeFilter()181 QtImageFilter *createNegativeFilter()
182 {
183 static int kernelmatrix[ 1 ] =
184   { -1 };
185     auto filter = new ConvolutionFilter();
186     filter->setName(QLatin1String("Negative"));
187     filter->setDescription(QObject::tr("Negates color channel(s).","ConvolutionFilter"));
188     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 1, 1), ConvolutionFilter::RGB, ConvolutionFilter::Extend, 1, 255);
189     return reinterpret_cast<QtImageFilter*>(filter);
190 }
191 
createRemoveChannelFilter()192 QtImageFilter *createRemoveChannelFilter()
193 {
194 static int kernelmatrix[ 1 ] =
195   { 0 };
196     auto filter = new ConvolutionFilter();
197     filter->setName(QLatin1String("RemoveChannel"));
198     filter->setDescription(QObject::tr("Removes channel(s). I.e sets the value of each channel it is processing to 0.","ConvolutionFilter"));
199     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 1, 1), ConvolutionFilter::RGBA, ConvolutionFilter::Extend, 1, 0);
200     return reinterpret_cast<QtImageFilter*>(filter);
201 }
202 
createConvolutionFilter()203 QtImageFilter *createConvolutionFilter()
204 {
205 static int kernelmatrix[ 1 ] =
206   { 1 };
207     auto filter = new ConvolutionFilter();
208     filter->setName(QLatin1String("ConvolutionFilter"));
209     filter->setDescription(QObject::tr("Generic convolutionfilter."));
210     filter->addKernel(QtConvolutionKernelMatrix(kernelmatrix, 1, 1), ConvolutionFilter::RGBA, ConvolutionFilter::Extend, 1, 0);
211     return reinterpret_cast<QtImageFilter*>(filter);
212 }
213 
createPunchFilter()214 QtImageFilter *createPunchFilter()
215 {
216     return reinterpret_cast<QtImageFilter*>(new PunchFilter());
217 }
218 
219 //typedef QtImageFilter*(*FnFactory)(void);
220 
221 static QMap<QByteArray, QtImageFilterFactory::ImageFilterFactoryFunction> g_availableFilters;
222 
registerDefaultImageFilters()223 static void registerDefaultImageFilters()
224 {
225     g_availableFilters.insert("GaussianBlur",        &createGaussianBlurFilter);
226     g_availableFilters.insert("Defocus",             &createDefocusFilter);
227     g_availableFilters.insert("Highlight",           &createHighlightFilter);
228     g_availableFilters.insert("Sharpen",             &createSharpenFilter);
229     g_availableFilters.insert("SharpenMore",         &createSharpenMoreFilter);
230     g_availableFilters.insert("SharpenEvenMore",     &createSharpenEvenMoreFilter);
231     g_availableFilters.insert("BigEdge",             &createBigEdgeFilter);
232     g_availableFilters.insert("Emboss",              &createEmbossFilter);
233     g_availableFilters.insert("EmbossColor",         &createEmbossColorFilter);
234     g_availableFilters.insert("EdgeDetect",          &createEdgeDetectFilter);
235     g_availableFilters.insert("Negative",            &createNegativeFilter);
236     g_availableFilters.insert("RemoveChannel",       &createRemoveChannelFilter);
237     g_availableFilters.insert("Punch",               &createPunchFilter);
238     g_availableFilters.insert("ConvolutionFilter",   &createConvolutionFilter);
239 }
240 /*!
241     \class QtImageFilterFactory
242 
243     \brief The QtImageFilterFactory class is used to create and manage
244     QtImageFilter objects.
245 
246     QtImageFilterFactory is part of the QtImageFilters solution, and is
247     used to create instances of the registered image filters. The
248     framework supports many popular image filters by default, among
249     these are gaussian blurring, embossing (see image below),
250     sharpening, defocus, punch/pinch and convolution filters.
251 
252     \image lena-edge.jpg
253 
254     The documentation for the createImageFilter() function provides a
255     complete list of all the supported image filters.
256 
257     Developers can extend the framework with their own custom image
258     filters by deriving from the QtImageFilter class. A list of the
259     currently registered filters, including custom filters, can be
260     retrieved using the imageFilterList() function.
261 
262     When creating a custom image filter, it must be registered using
263     the registerImageFilter() function before instances can be created
264     using the createImageFilter() function. For example:
265 
266     \quotefromfile ../examples/imagetool/imagetoolwidget.cpp
267     \skipto qtRegisterImageFilter
268     \printline  qtRegisterImageFilter
269     \skipto QStringList
270     \printuntil m_imageFilters
271 
272     The registerImageFilter() function requires an
273     ImageFilterFactoryFunction pointer and the name of the image
274     filter. ImageFilterFactoryFunction is a type definition for a
275     function that can create and return a QtImageFilter object of a
276     given filter type.
277 
278     Due to compiler limitations, the template version of the
279     registerImageFilter() function is not available on all
280     platforms (the related qtRegisterImageFilter() function is
281     provided as a work-around for the MSVC 6 compiler).
282 
283     \sa QtImageFilter
284 */
285 
286 /*!
287     \typedef QtImageFilterFactory::ImageFilterFactoryFunction
288 
289     This is a type definition for a pointer to a function with the
290     following signature:
291 
292     \code
293         QtImageFilter *myFilterFactoryFunc(void);
294     \endcode
295 
296     \sa registerImageFilter()
297 */
298 /*!
299     Creates an instance of the image filter specified by the given \a
300     name. Returns true if the image filter was successfully
301     initialized; otherwise false.
302 
303     The given filter must be registered using the
304     registerImageFilter() function. The following image filters are
305     registered by default:
306 
307     \table
308     \header
309         \o Filter Name
310         \o Filter Operation
311         \o Supported Options
312     \row
313         \o ConvolutionFilter
314         \o Creates a custom convolutionfilter
315         \o ConvolutionKernelMatrix, FilterChannels, FilterBorderPolicy, ConvolutionDivisor, ConvolutionBias
316     \row
317         \o GaussianBlur
318         \o Creates a gaussian blur filter.
319         \o Radius, FilterChannels, FilterBorderPolicy
320     \row
321         \o Defocus
322         \o Blurs the image.
323         \o FilterChannels, FilterBorderPolicy
324     \row
325         \o Highlight
326         \o
327         \o FilterChannels, FilterBorderPolicy
328     \row
329         \o Sharpen
330         \o Sharpens the image
331         \o FilterChannels, FilterBorderPolicy
332     \row
333         \o SharpenMore
334         \o Sharpens the image
335         \o FilterChannels, FilterBorderPolicy
336     \row
337         \o SharpenEvenMore
338         \o Sharpens the image
339         \o FilterChannels, FilterBorderPolicy
340     \row
341         \o EdgeDetect
342         \o Edge detection filter
343         \o
344     \row
345         \o BigEdge
346         \o Edge detection filter (gives thicker edges)
347         \o FilterChannels, FilterBorderPolicy
348     \row
349         \o Emboss
350         \o Embosses the image (does not preserve color information)
351         \o FilterChannels, FilterBorderPolicy
352     \row
353         \o EmbossColor
354         \o Embosses the image (tries to preserve color information)
355         \o FilterChannels, FilterBorderPolicy
356     \row
357         \o Negative
358         \o Negates a color channel.
359         \o FilterChannels, FilterBorderPolicy
360     \row
361         \o RemoveChannel
362         \o Removes a color/alpha channel
363         \o FilterChannels, FilterBorderPolicy
364     \row
365         \o Punch
366         \o Distorts an image using a pinch/punch effect
367         \o Center, Radius, Force. Force should be in the interval [-1.0, 1.0]
368     \endtable
369 
370     \sa registerImageFilter()
371 */
createImageFilter(const QString & name)372 QtImageFilter *QtImageFilterFactory::createImageFilter(const QString &name)
373 {
374     if (g_availableFilters.isEmpty()) {
375         registerDefaultImageFilters();
376     }
377 
378     ImageFilterFactoryFunction fnFactory = g_availableFilters.value(name.toLatin1());
379     return fnFactory ? fnFactory() : nullptr;
380 }
381 
382 /*!
383     Returns a list of the currently registered image filters.
384 
385     \sa registerImageFilter()
386 */
imageFilterList()387 QStringList QtImageFilterFactory::imageFilterList()
388 {
389     QStringList ss;
390     if (g_availableFilters.isEmpty()) {
391         registerDefaultImageFilters();
392     }
393 
394     for (QMap<QByteArray, ImageFilterFactoryFunction>::iterator it = g_availableFilters.begin(); it != g_availableFilters.end(); ++it) {
395 		ss.append(QLatin1String(it.key()));
396     }
397     return ss;
398 }
399 
400 /*!
401     \fn void QtImageFilterFactory::registerImageFilter(const QString &name, ImageFilterFactoryFunction function)
402 
403     Registers an image filter factory function, where the given \a
404     name is associated with the specified factory \a function
405     returning a image filter object of the specified type.
406 
407     \sa imageFilterList(), createImageFilter()
408 */
registerImageFilter(const QString & name,ImageFilterFactoryFunction func)409 void QtImageFilterFactory::registerImageFilter(const QString &name, ImageFilterFactoryFunction func)
410 {
411     if (g_availableFilters.isEmpty()) {
412         registerDefaultImageFilters();
413     }
414     g_availableFilters.insert(name.toLatin1(), func);
415 }
416 
417 /*!
418     \fn QtImageFilter *QtImageFilterFactory::automaticFilterCreator()
419     \internal
420 
421     This is a template function that creates a factory function for
422     creating a QtImageFilter object of type \c{T}. For example:
423 
424     This function is also used as a helper function for the
425     registerImageFilter(const QString &name) function.
426 
427     \warning Due to compiler limitations, this function is not
428     available on all platforms. In particular it is not available with
429     MSVC 6; use qtAutomaticFilterCreator() instead to support that
430     compiler version.
431 
432     \sa registerImageFilter()
433 */
434 
435 /*!
436     \fn QtImageFilter *qtAutomaticFilterCreator(const T* dummy = 0)
437     \relates QtImageFilterFactory
438     \internal
439 
440     This function is equivalent to
441     QtImageFilterFactory::automaticFilterCreator()
442 
443     It is provided as a work-around for the MSVC 6 compiler, which
444     doesn't support member template functions. There is no need to
445     pass any value for the \a dummy parameter; it is only there
446     because of an MSVC 6 limitation.
447 
448     \sa QtImageFilterFactory::automaticFilterCreator()
449 */
450 
451 /*!
452     \fn void QtImageFilterFactory::registerImageFilter(const QString &name)
453 
454     This is a template function, registering the image filter with the
455     given \a name together with a factory function that returns a new
456     instance of an image filter of type \c{T}. For example:
457 
458     \code
459         registerImageFilter<MirrorFilter>(QLatin1String("MirrorFilter"));
460     \endcode
461 
462     \warning Due to compiler limitations, this function is not
463     available on all platforms. In particular it is not available with
464     MSVC 6; use qtRegisterImageFilter() instead to support that
465     compiler version.
466 
467     \sa createImageFilter()
468 */
469 
470 /*!
471     \fn qtRegisterImageFilter(const QString &name, T* dummy )
472     \relates QtImageFilterFactory
473 
474     This function is equivalent to the template version of the
475     QtImageFilterFactory::registerImageFilter() function.It registers
476     the image filter with the given \a name together with a factory
477     function that returns a new instance of the image filter.
478 
479     It is provided as a work-around for the MSVC 6 compiler, which
480     doesn't support member template functions. Note that there is no
481     need to pass any value for the \a dummy parameter; it is only
482     there because of an MSVC 6 limitation.
483 
484     \sa QtImageFilterFactory::registerImageFilter()
485 */
486 
487