Commit 7954524f authored by Cyrille Berger's avatar Cyrille Berger

- add a new class KisMathToolbox which contains functions for wavelet...

- add a new class KisMathToolbox which contains functions for wavelet transformation (and in the futur pyramid and FFT), as those functions might be colorspace dependant, the implmentation is done in KisBasicMathToolbox (which works for nearly all colorspaces, except those with an angle and wetcolorspaces for which no implementation will ever works)
- make the wavelet noise reducert uses KisMathToolbox


svn path=/trunk/koffice/; revision=489414
parent ce0c96e1
......@@ -12,49 +12,17 @@ INCLUDES = \
lib_LTLIBRARIES = libkritaimage.la
libkritaimage_la_SOURCES = \
kis_alpha_mask.cc \
kis_autobrush_resource.cc \
kis_autogradient_resource.cc \
kis_background.cc \
kis_boundary.cc \
kis_brush.cc \
kis_command.cc \
kis_convolution_painter.cc \
kis_fill_painter.cc \
kis_filter.cc \
kis_filter_registry.cc \
kis_filter_strategy.cc \
kis_gradient.cc \
kis_gradient_painter.cc \
kis_histogram.cc \
kis_image.cc \
kis_imagepipe_brush.cc \
kis_iterator.cc \
kis_iterators_pixel.cc \
kis_layer.cc \
kis_meta_registry.cc \
kis_nameserver.cc \
kis_painter.cc \
kis_paintop.cc \
kis_paintop_registry.cc \
kis_palette.cc \
kis_pattern.cc \
kis_rect.cc \
kis_resource.cc \
kis_rotate_visitor.cc \
kis_scale_visitor.cc \
kis_selected_transaction.cc \
kis_selection.cc \
kis_strategy_move.cc \
kis_transaction.cc \
kis_transform_visitor.cc \
kis_vec.cc \
kis_paint_device_impl.cc \
kis_paint_device_iface.cc \
kis_paint_device_iface.skel \
kis_image_iface.cc \
kis_image_iface.skel
libkritaimage_la_SOURCES = kis_alpha_mask.cc kis_autobrush_resource.cc \
kis_autogradient_resource.cc kis_background.cc kis_boundary.cc kis_brush.cc kis_command.cc \
kis_convolution_painter.cc kis_fill_painter.cc kis_filter.cc kis_filter_registry.cc \
kis_filter_strategy.cc kis_gradient.cc kis_gradient_painter.cc kis_histogram.cc kis_image.cc \
kis_imagepipe_brush.cc kis_iterator.cc kis_iterators_pixel.cc kis_layer.cc \
kis_meta_registry.cc kis_nameserver.cc kis_painter.cc kis_paintop.cc kis_paintop_registry.cc \
kis_palette.cc kis_pattern.cc kis_rect.cc kis_resource.cc kis_rotate_visitor.cc \
kis_scale_visitor.cc kis_selected_transaction.cc kis_selection.cc kis_strategy_move.cc \
kis_transaction.cc kis_transform_visitor.cc kis_vec.cc kis_paint_device_impl.cc \
kis_paint_device_iface.cc kis_paint_device_iface.skel kis_image_iface.cc kis_image_iface.skel \
kis_basic_math_toolbox.cpp kis_math_toolbox.cpp
noinst_HEADERS = \
kis_paint_device_visitor.h \
......
/*
* This file is part of the KDE project
*
* Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
*
* 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 of the License, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kis_basic_math_toolbox.h"
KisBasicMathToolbox::KisBasicMathToolbox()
: KisMathToolbox(KisID("Basic"))
{
}
KisBasicMathToolbox::~KisBasicMathToolbox()
{
}
void KisBasicMathToolbox::wavetrans(KisMathToolbox::KisWavelet* wav, KisMathToolbox::KisWavelet* buff, uint halfsize)
{
uint l = (2*halfsize)*wav->depth*sizeof(float);
for(uint i = 0; i < halfsize; i++)
{
float * itLL = buff->coeffs + i*buff->size*buff->depth;
float * itHL = buff->coeffs + (i*buff->size + halfsize)*buff->depth;
float * itLH = buff->coeffs + (halfsize+i)*buff->size*buff->depth;
float * itHH = buff->coeffs + ( (halfsize+i)*buff->size + halfsize)*buff->depth;
float * itS11 = wav->coeffs + 2*i*wav->size*wav->depth;
float * itS12 = wav->coeffs + (2*i*wav->size+1)*wav->depth;
float * itS21 = wav->coeffs + (2*i+1)*wav->size*wav->depth;
float * itS22 = wav->coeffs + ((2*i+1)*wav->size+1)*wav->depth;
for(uint j = 0; j < halfsize; j++)
{
for( uint k = 0; k < wav->depth; k++)
{
*(itLL++) = (*itS11 + *itS12 + *itS21 + *itS22) * M_SQRT1_2;
*(itHL++) = (*itS11 - *itS12 + *itS21 - *itS22) * M_SQRT1_2;
*(itLH++) = (*itS11 + *itS12 - *itS21 - *itS22) * M_SQRT1_2;
*(itHH++) = (*(itS11++) - *(itS12++) - *(itS21++) + *(itS22++)) * M_SQRT1_2;
}
itS11 += wav->depth; itS12 += wav->depth;
itS21 += wav->depth; itS22 += wav->depth;
}
emit nextStep();
}
for(uint i = 0; i < halfsize; i++)
{
uint p = i*wav->size*wav->depth;
memcpy(wav->coeffs + p, buff->coeffs + p, l);
p = (i + halfsize )*wav->size*wav->depth;
memcpy(wav->coeffs + p, buff->coeffs + p, l);
}
if(halfsize != 1)
{
wavetrans(wav, buff, halfsize/2);
}
}
void KisBasicMathToolbox::waveuntrans(KisMathToolbox::KisWavelet* wav, KisMathToolbox::KisWavelet* buff, uint halfsize)
{
uint l = (2*halfsize)*wav->depth*sizeof(float);
for(uint i = 0; i < halfsize; i++)
{
float * itLL = wav->coeffs + i*buff->size*buff->depth;
float * itHL = wav->coeffs + (i*buff->size + halfsize)*buff->depth;
float * itLH = wav->coeffs + (halfsize+i)*buff->size*buff->depth;
float * itHH = wav->coeffs + ( (halfsize+i)*buff->size + halfsize)*buff->depth;
float * itS11 = buff->coeffs + 2*i*wav->size*wav->depth;
float * itS12 = buff->coeffs + (2*i*wav->size+1)*wav->depth;
float * itS21 = buff->coeffs + (2*i+1)*wav->size*wav->depth;
float * itS22 = buff->coeffs + ((2*i+1)*wav->size+1)*wav->depth;
for(uint j = 0; j < halfsize; j++)
{
for( uint k = 0; k < wav->depth; k++)
{
*(itS11++) = (*itLL + *itHL + *itLH + *itHH)*0.25*M_SQRT2;
*(itS12++) = (*itLL - *itHL + *itLH - *itHH)*0.25*M_SQRT2;
*(itS21++) = (*itLL + *itHL - *itLH - *itHH)*0.25*M_SQRT2;
*(itS22++) = (*(itLL++) - *(itHL++) - *(itLH++) + *(itHH++))*0.25*M_SQRT2;
}
itS11 += wav->depth; itS12 += wav->depth;
itS21 += wav->depth; itS22 += wav->depth;
}
emit nextStep();
}
for(uint i = 0; i < halfsize; i++)
{
uint p = i*wav->size*wav->depth;
memcpy(wav->coeffs + p, buff->coeffs + p, l);
p = (i + halfsize )*wav->size*wav->depth;
memcpy(wav->coeffs + p, buff->coeffs + p, l);
}
if(halfsize != wav->size/2)
{
waveuntrans(wav, buff, halfsize*2);
}
}
KisMathToolbox::KisWavelet* KisBasicMathToolbox::fastWaveletTransformation(KisPaintDeviceImplSP src, const QRect& rect, KisWavelet* buff)
{
if(buff == 0)
{
buff = initWavelet( src, rect );
}
KisWavelet* wav = initWavelet( src, rect );
transformToFR(src, wav, rect);
wavetrans(wav, buff, wav->size / 2);
return wav;
}
void KisBasicMathToolbox::fastWaveletUntransformation(KisPaintDeviceImplSP dst, const QRect& rect, KisWavelet* wav, KisWavelet* buff)
{
if(buff == 0)
{
buff = initWavelet( dst, rect );
}
waveuntrans(wav, buff, 1 );
transformFromFR(dst, wav, rect);
}
/*
* This file is part of the KDE project
*
* Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
*
* 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 of the License, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef KIS_BASIC_MATH_TOOLBOX_H
#define KIS_BASIC_MATH_TOOLBOX_H
#include "kis_math_toolbox.h"
/**
* This class implement KisMathToolbox for most colorspaces, only colorspaces with "angular"
* channels need to reimplement the functions
*/
class KisBasicMathToolbox : public KisMathToolbox
{
public:
KisBasicMathToolbox();
~KisBasicMathToolbox();
public:
virtual KisWavelet* fastWaveletTransformation(KisPaintDeviceImplSP src, const QRect&, KisWavelet* buff = 0);
virtual void fastWaveletUntransformation(KisPaintDeviceImplSP dst, const QRect&, KisWavelet* wav, KisWavelet* buff = 0);
private:
void wavetrans(KisWavelet* wav, KisWavelet* buff, uint halfsize);
void waveuntrans(KisWavelet* wav, KisWavelet* buff, uint halfsize);
};
#endif
......@@ -123,7 +123,7 @@ public:
bool progressEnabled() const { return m_progressEnabled; }
inline bool cancelRequested() const { return m_progressEnabled && m_cancelRequested; }
protected:
protected slots:
// Convenience functions for progress display.
void setProgressTotalSteps(Q_INT32 totalSteps);
......@@ -131,7 +131,7 @@ protected:
void incProgress();
void setProgressStage(const QString& stage, Q_INT32 progress);
void setProgressDone();
inline Q_INT32 progress() { return m_progressSteps; }
private:
bool m_cancelRequested;
bool m_progressEnabled;
......
/*
* This file is part of the KDE project
*
* Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
*
* 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 of the License, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kis_math_toolbox.h"
#include <half.h>
#include "kis_basic_math_toolbox.h"
#include "kis_iterators_pixel.h"
KisMathToolbox::KisMathToolbox(KisID id) : m_id(id)
{
}
KisMathToolbox::~KisMathToolbox()
{
}
KisMathToolboxFactoryRegistry::KisMathToolboxFactoryRegistry()
{
add(new KisBasicMathToolbox());
}
KisMathToolboxFactoryRegistry::~KisMathToolboxFactoryRegistry()
{
}
template<typename T>
double toDouble(Q_UINT8* data, int channelpos )
{
return (float)( *((T*)(data + channelpos)) );
}
typedef double (*PtrToDouble)(Q_UINT8*, int);
template<typename T>
void fromDouble(Q_UINT8* data, int channelpos, double v )
{
*((T*)(data + channelpos)) = (T)v;
}
typedef void (*PtrFromDouble)(Q_UINT8*, int, double);
void KisMathToolbox::transformToFR(KisPaintDeviceImplSP src, KisFloatRepresentation* fr, const QRect& rect)
{
Q_INT32 depth = src->colorSpace()->nColorChannels();
PtrToDouble f[depth];
QValueVector<KisChannelInfo *> cis = src->colorSpace()->channels();
for(uint k = 0; k < depth; k++)
{
switch( cis[k]->channelValueType() )
{
case KisChannelInfo::UINT8:
f[k] = toDouble<Q_UINT8>;
break;
case KisChannelInfo::UINT16:
f[k] = toDouble<Q_UINT16>;
break;
case KisChannelInfo::FLOAT16:
f[k] = toDouble<half>;
break;
case KisChannelInfo::FLOAT32:
f[k] = toDouble<float>;
break;
case KisChannelInfo::INT8:
f[k] = toDouble<Q_INT8>;
break;
case KisChannelInfo::INT16:
f[k] = toDouble<Q_INT16>;
break;
default:
kdDebug() << "Unsupported value type in KisMathToolbox" << endl;
return;
}
}
for(int i = rect.y(); i < rect.height(); i++)
{
KisHLineIteratorPixel srcIt = src->createHLineIterator(rect.x(), i, rect.width(), false );
float *dstIt = fr->coeffs + (i-rect.y()) * fr->size * fr->depth;
while( ! srcIt.isDone() )
{
Q_UINT8* v1 = srcIt.rawData();
for( int k = 0; k < depth; k++)
{
*dstIt = f[k](v1, cis[k]->pos());
++dstIt;
}
++srcIt;
}
}
}
void KisMathToolbox::transformFromFR(KisPaintDeviceImplSP dst, KisFloatRepresentation* fr, const QRect& rect)
{
Q_INT32 depth = dst -> colorSpace() -> nColorChannels();
PtrFromDouble f[depth];
QValueVector<KisChannelInfo *> cis = dst->colorSpace()->channels();
for(uint k = 0; k < depth; k++)
{
switch( cis[k]->channelValueType() )
{
case KisChannelInfo::UINT8:
f[k] = fromDouble<Q_UINT8>;
break;
case KisChannelInfo::UINT16:
f[k] = fromDouble<Q_UINT16>;
break;
case KisChannelInfo::FLOAT16:
f[k] = fromDouble<half>;
break;
case KisChannelInfo::FLOAT32:
f[k] = fromDouble<float>;
break;
case KisChannelInfo::INT8:
f[k] = fromDouble<Q_INT8>;
break;
case KisChannelInfo::INT16:
f[k] = fromDouble<Q_INT16>;
break;
default:
kdDebug() << "Unsupported value type in KisMathToolbox" << endl;
return;
}
}
for(int i = rect.y(); i < rect.height(); i++)
{
KisHLineIteratorPixel dstIt = dst->createHLineIterator(rect.x(), i, rect.width(), true );
float *srcIt = fr->coeffs + (i-rect.y()) * fr->size * fr->depth;
while( ! dstIt.isDone() )
{
Q_UINT8* v1 = dstIt.rawData();
for( int k = 0; k < depth; k++)
{
f[k](v1, cis[k]->pos(), *srcIt);
++srcIt;
}
++dstIt;
}
}
}
/*
* This file is part of the KDE project
*
* Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
*
* 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 of the License, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef KIS_MATH_TOOLBOX_H
#define KIS_MATH_TOOLBOX_H
#include <qobject.h>
// typedef unsigned int uint;
#include <kis_generic_registry.h>
#include "kis_paint_device_impl.h"
#include "kis_types.h"
class KisMathToolbox : public QObject {
Q_OBJECT
public:
struct KisFloatRepresentation {
KisFloatRepresentation(uint nsize, uint ndepth) : coeffs(new float[nsize*nsize*ndepth]), size(nsize), depth(ndepth) { }
~KisFloatRepresentation() { delete coeffs; }
float* coeffs;
uint size;
uint depth;
};
typedef KisFloatRepresentation KisWavelet;
public:
KisMathToolbox(KisID id);
~KisMathToolbox();
public:
inline KisID id() { return m_id; };
/**
* This function initialize a wavelet structure
* @param lay the layer that will be used for the transformation
*/
inline KisWavelet* initWavelet(KisPaintDeviceImplSP lay, const QRect&);
inline uint fastWaveletTotalSteps(const QRect&);
/**
* This function reconstruct the layer from the information of a wavelet
* @param src layer from which the wavelet will be computed
* @param buff if set to 0, the buffer will be initialized by the function,
* you might want to give a buff to the function if you want to use the same buffer
* in transformToWavelet and in untransformToWavelet, use initWavelet to initialize
* the buffer
*/
virtual KisWavelet* fastWaveletTransformation(KisPaintDeviceImplSP src, const QRect&, KisWavelet* buff = 0) =0;
/**
* This function reconstruct the layer from the information of a wavelet
* @param dst layer on which the wavelet will be untransform
* @param wav the wavelet
* @param buff if set to 0, the buffer will be initialized by the function,
* you might want to give a buff to the function if you want to use the same buffer
* in transformToWavelet and in untransformToWavelet, use initWavelet to initialize
* the buffer
*/
virtual void fastWaveletUntransformation(KisPaintDeviceImplSP dst, const QRect&, KisWavelet* wav, KisWavelet* buff = 0) =0;
signals:
void nextStep();
protected:
/**
* This function transform a paint device into a KisFloatRepresentation, this function is colorspace independant,
* for Wavelet, Pyramid and FFT the data is allways the exact value of the channel stored in a float.
*/
void transformToFR(KisPaintDeviceImplSP src, KisFloatRepresentation*, const QRect&);
/**
* This function transform a KisFloatRepresentation into a paint device, this function is colorspace independant,
* for Wavelet, Pyramid and FFT the data is allways the exact value of the channel stored in a float.
*/
void transformFromFR(KisPaintDeviceImplSP dst, KisFloatRepresentation*, const QRect&);
private:
KisID m_id;
};
class KisMathToolboxFactoryRegistry : public KisGenericRegistry<KisMathToolbox*> {
public:
KisMathToolboxFactoryRegistry();
~KisMathToolboxFactoryRegistry();
};
inline KisMathToolbox::KisWavelet* KisMathToolbox::initWavelet(KisPaintDeviceImplSP src, const QRect& rect)
{
int size;
int maxrectsize = (rect.height() < rect.width()) ? rect.width() : rect.height();
for(size = 2; size < maxrectsize; size *= 2) ;
Q_INT32 depth = src -> colorSpace() -> nColorChannels();
return new KisWavelet(size, depth);
}
inline uint KisMathToolbox::fastWaveletTotalSteps(const QRect& rect)
{
uint size, steps;
int maxrectsize = (rect.height() < rect.width()) ? rect.width() : rect.height();
steps = 0;
for(size = 2; size < maxrectsize; size *= 2) steps += size / 2; ;
return steps;
}
#endif
......@@ -21,6 +21,7 @@
#include <kglobal.h>
#include <kis_colorspace_factory_registry.h>
#include <kis_math_toolbox.h>
#include <kis_meta_registry.h>
KisMetaRegistry * KisMetaRegistry::m_singleton = 0;
......@@ -48,6 +49,7 @@ KisMetaRegistry::KisMetaRegistry()
profileFilenames += d.entryList();
m_csRegistry = new KisColorSpaceFactoryRegistry(profileFilenames);
m_mtRegistry = new KisMathToolboxFactoryRegistry();
}
KisMetaRegistry::~KisMetaRegistry()
......@@ -62,7 +64,3 @@ KisMetaRegistry * KisMetaRegistry::instance()
return KisMetaRegistry::m_singleton;
}
KisColorSpaceFactoryRegistry * KisMetaRegistry::csRegistry()
{
return m_csRegistry;
}
......@@ -19,6 +19,7 @@
#define _KIS_META_REGISTRY_
class KisColorSpaceFactoryRegistry;
class KisMathToolboxFactoryRegistry;
/**
* A single singleton that provides access to several registries.
......@@ -32,8 +33,8 @@ public:
virtual ~KisMetaRegistry();
static KisMetaRegistry* instance();
KisColorSpaceFactoryRegistry * csRegistry();
KisColorSpaceFactoryRegistry * csRegistry() { return m_csRegistry; };
KisMathToolboxFactoryRegistry* mtRegistry() { return m_mtRegistry; };
private:
KisMetaRegistry();
......@@ -43,5 +44,6 @@ private:
static KisMetaRegistry * m_singleton;
KisColorSpaceFactoryRegistry * m_csRegistry;
KisMathToolboxFactoryRegistry* m_mtRegistry;
};
#endif
......@@ -12,22 +12,11 @@ if have_openexr
OPENEXR_SOURCES=kis_f16half_base_colorspace.cc
endif
libkritacolor_la_SOURCES = \
kis_color.cc \
kis_colorspace.cc \
kis_colorspace_iface.cc \
kis_colorspace_iface.skel \
kis_composite_op.cc \
kis_profile.cc \
kis_histogram_producer.cc \
kis_basic_histogram_producers.cc \
kis_abstract_colorspace.cc \
kis_colorspace_factory_registry.cc \
kis_color_conversions.cc \
kis_u8_base_colorspace.cc \
kis_u16_base_colorspace.cc \
kis_f32_base_colorspace.cc \
$(OPENEXR_SOURCES)
libkritacolor_la_SOURCES = kis_color.cc kis_colorspace.cc \
kis_colorspace_iface.cc kis_colorspace_iface.skel kis_composite_op.cc kis_profile.cc \
kis_histogram_producer.cc kis_basic_histogram_producers.cc kis_abstract_colorspace.cc \
kis_colorspace_factory_registry.cc kis_color_conversions.cc kis_u8_base_colorspace.cc \
kis_u16_base_colorspace.cc kis_f32_base_colorspace.cc $(OPENEXR_SOURCES)
libkritacolor_la_LDFLAGS = -version-info 1:0:0 -no-undefined $(all_libraries)
libkritacolor_la_LIBADD = colorspaces/libkritacolorspaces.la $(LCMS_LIBS) $(LIB_KPARTS) $(LIB_KDECORE) $(LIB_QT) $(OPENEXR_LIBS)
......@@ -51,3 +40,5 @@ SUBDIRS = colorspaces . $(TESTSDIR)
kde_servicetypes_DATA = krita_colorspace.desktop
METASOURCES = AUTO
......@@ -516,6 +516,11 @@ Q_UINT8 KisAbstractColorSpace::intensity8(const Q_UINT8 * src) const
}
KisID KisAbstractColorSpace::mathToolboxID() const
{
return KisID("Basic");
}
void KisAbstractColorSpace::bitBlt(Q_UINT8 *dst,
Q_INT32 dststride,
KisColorSpace * srcSpace,
......