Commit 273068d5 authored by Cyrille Berger's avatar Cyrille Berger

- move the new bitBlts to KoColorSpace

- add to/fromRgb16 (do not use anymore QColor !)
- templating of KoCompositeOver
- change KoRgbU32ColorSpace to KoRgbU16ColorSpace

svn path=/trunk/koffice/; revision=588287
parent 260d9f20
......@@ -12,6 +12,7 @@ set(pigment_SRCS
KoColorSpaceRegistry.cpp
KoColor.cpp
KoColorSpace.cpp
KoColorSpaceMaths.cpp
KoCompositeOp.cpp
KoColorProfile.cpp
KoLcmsColorSpaceTrait.cpp
......@@ -21,7 +22,7 @@ set(pigment_SRCS
${FILE_OPENEXR_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/colorspaces/KoAlphaColorSpace.cpp
${CMAKE_CURRENT_SOURCE_DIR}/colorspaces/KoLabColorSpace.cpp
${CMAKE_CURRENT_SOURCE_DIR}/colorspaces/KoRgbU32ColorSpace.cpp
${CMAKE_CURRENT_SOURCE_DIR}/colorspaces/KoRgbU16ColorSpace.cpp
)
kde4_automoc(${pigment_SRCS})
......
......@@ -18,6 +18,9 @@
*/
#include "KoColorSpace.h"
#include <kdebug.h>
#include "KoCompositeOp.h"
KoColorSpace::KoColorSpace(const QString &id, const QString &name, KoColorSpaceRegistry * parent)
......@@ -118,3 +121,107 @@ void KoColorSpace::bitBlt(quint8 *dst,
bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, m_compositeOps.value( COMPOSITE_OVER ) );
}
}
void KoColorSpace::bitBlt(quint8 *dst,
qint32 dststride,
KoColorSpace * srcSpace,
const quint8 *src,
qint32 srcRowStride,
const quint8 *srcAlphaMask,
qint32 maskRowStride,
quint8 opacity,
qint32 rows,
qint32 cols,
const KoCompositeOp * op,
const QBitArray & channelFlags)
{
if (rows <= 0 || cols <= 0)
return;
if (this != srcSpace) {
quint32 len = pixelSize() * rows * cols;
// If our conversion cache is too small, extend it.
if (!m_conversionCache.resize( len, Q3GArray::SpeedOptim )) {
kWarning() << "Could not allocate enough memory for the conversion!\n";
// XXX: We should do a slow, pixel by pixel bitblt here...
abort();
}
for (qint32 row = 0; row < rows; row++) {
srcSpace->convertPixelsTo(src + row * srcRowStride,
m_conversionCache.data() + row * cols * pixelSize(), this,
cols);
}
// The old srcRowStride is no longer valid because we converted to the current cs
srcRowStride = cols * pixelSize();
op->composite( dst, dststride,
m_conversionCache.data(), srcRowStride,
srcAlphaMask, maskRowStride,
rows, cols,
opacity, channelFlags );
}
else {
op->composite( dst, dststride,
src, srcRowStride,
srcAlphaMask, maskRowStride,
rows, cols,
opacity, channelFlags );
}
}
// XXX: I don't wan this code duplication, but also don't want an
// extra function call in this critical section of code. What to
// do?
void KoColorSpace::bitBlt(quint8 *dst,
qint32 dststride,
KoColorSpace * srcSpace,
const quint8 *src,
qint32 srcRowStride,
const quint8 *srcAlphaMask,
qint32 maskRowStride,
quint8 opacity,
qint32 rows,
qint32 cols,
const KoCompositeOp * op)
{
if (rows <= 0 || cols <= 0)
return;
if (this != srcSpace) {
quint32 len = pixelSize() * rows * cols;
// If our conversion cache is too small, extend it.
if (!m_conversionCache.resize( len, Q3GArray::SpeedOptim )) {
kWarning() << "Could not allocate enough memory for the conversion!\n";
// XXX: We should do a slow, pixel by pixel bitblt here...
abort();
}
for (qint32 row = 0; row < rows; row++) {
srcSpace->convertPixelsTo(src + row * srcRowStride,
m_conversionCache.data() + row * cols * pixelSize(), this,
cols);
}
// The old srcRowStride is no longer valid because we converted to the current cs
srcRowStride = cols * pixelSize();
op->composite( dst, dststride,
m_conversionCache.data(), srcRowStride,
srcAlphaMask, maskRowStride,
rows, cols,
opacity);
}
else {
op->composite( dst, dststride,
src,srcRowStride,
srcAlphaMask, maskRowStride,
rows, cols,
opacity);
}
}
......@@ -26,6 +26,8 @@
#include <QImage>
#include <QBitArray>
#include <QHash>
#include <Q3MemArray>
#include <q3valuevector.h>
#include <q3valuelist.h>
......@@ -58,6 +60,7 @@ enum ColorSpaceIndependence {
TO_RGBA16
};
// TODO: constify all function of KisColorSpace
// TODO: RgbA16 convert function must be set to pure virtual
/**
* A KoColorSpace is the definition of a certain color space.
*
......@@ -320,6 +323,25 @@ public:
*/
virtual void fromLabA16(const quint8 * src, quint8 * dst, const quint32 nPixels) const = 0;
/**
* Convert the specified data to Rgb 16 bits. All colorspaces are guaranteed to support this
*
* @param src the source data
* @param dst the destination data
* @param nPixels the number of source pixels
*/
virtual void toRgbA16(const quint8 * src, quint8 * dst, const quint32 nPixels) const {};
/**
* Convert the specified data from Rgb 16 bits. to this colorspace. All colorspaces are
* guaranteed to support this.
*
* @param src the pixels in 16 bit rgb format
* @param dst the destination data
* @param nPixels the number of pixels in the array
*/
virtual void fromRgbA16(const quint8 * src, quint8 * dst, const quint32 nPixels) const {};
/**
* Convert a byte array of srcLen pixels *src to the specified color space
* and put the converted bytes into the prepared byte array *dst.
......@@ -472,22 +494,7 @@ public:
qint32 rows,
qint32 cols,
const KoCompositeOp * op,
const QBitArray & channelFlags)
{
Q_UNUSED(dst);
Q_UNUSED(dststride);
Q_UNUSED(srcSpace);
Q_UNUSED(src);
Q_UNUSED(srcRowStride);
Q_UNUSED(srcAlphaMask);
Q_UNUSED(maskRowStride);
Q_UNUSED(opacity);
Q_UNUSED(rows);
Q_UNUSED(cols);
Q_UNUSED(op);
Q_UNUSED(channelFlags);
}
const QBitArray & channelFlags);
/**
* Convenience function for the above where all channels are turned on.
*/
......@@ -501,20 +508,7 @@ public:
quint8 opacity,
qint32 rows,
qint32 cols,
const KoCompositeOp * op)
{
Q_UNUSED(dst);
Q_UNUSED(dststride);
Q_UNUSED(srcSpace);
Q_UNUSED(src);
Q_UNUSED(srcRowStride);
Q_UNUSED(srcAlphaMask);
Q_UNUSED(maskRowStride);
Q_UNUSED(opacity);
Q_UNUSED(rows);
Q_UNUSED(cols);
Q_UNUSED(op);
}
const KoCompositeOp * op);
/**
* Convenience function for the above if you don't have the composite op object yet.
......@@ -566,6 +560,7 @@ protected:
KoColorSpaceRegistry * m_parent;
Q3ValueVector<KoChannelInfo *> m_channels;
QHash<QString, KoCompositeOp *> m_compositeOps;
Q3MemArray<quint8> m_conversionCache; // XXX: This will be a bad problem when we have threading.
};
......
......@@ -24,6 +24,7 @@
#include <KoColorSpace.h>
#include <KoColorSpaceMaths.h>
#include <KoIntegerMaths.h>
namespace {
......@@ -95,7 +96,7 @@ class KoColorSpaceAbstract : public KoColorSpace {
virtual quint32 nColorChannels() const { return _CSTraits::channels_nb - 1; }
virtual quint32 nChannels() const { return _CSTraits::channels_nb; };
virtual quint32 pixelSize() const { return _CSTraits::channels_nb * sizeof(_CSTraits::channels_nb); }
virtual quint32 pixelSize() const { return _CSTraits::channels_nb * sizeof(typename _CSTraits::channels_type); }
Q3ValueVector<KoChannelInfo *> channels()
{
......@@ -279,7 +280,7 @@ class KoColorSpaceAbstract : public KoColorSpace {
return KoID("Basic");
}
private:
protected:
inline const typename _CSTraits::channels_type* nativeArray(const quint8 * a) const { return reinterpret_cast<const typename _CSTraits::channels_type*>(a); }
inline typename _CSTraits::channels_type* nativeArray(quint8 * a) const { return reinterpret_cast<typename _CSTraits::channels_type*>(a); }
};
......
......@@ -17,8 +17,12 @@
* Boston, MA 02110-1301, USA.
*/
#include <qglobal.h>
#include <KoColorSpaceMaths.h>
#include <KoIntegerMaths.h>
// TODO: use more functions from KoIntegersMaths to do the computation
/// This specialization is needed because the default implementation won't work when scaling up
......
......@@ -20,8 +20,6 @@
#ifndef KOCOLORSPACEMATHS_H_
#define KOCOLORSPACEMATHS_H_
#include <KoIntegerMaths.h>
template<typename _T>
class KoColorSpaceMathsTraits {
public:
......@@ -37,7 +35,7 @@ template<>
class KoColorSpaceMathsTraits<quint8> {
public:
typedef qint32 compositetype;
inline static qint64 max() { return 0x000F; }
inline static qint64 max() { return 0x00FF; }
inline static qint64 min() { return 0; }
inline static qint8 bits() { return 8; }
};
......@@ -46,7 +44,7 @@ template<>
class KoColorSpaceMathsTraits<quint16> {
public:
typedef qint32 compositetype;
inline static qint64 max() { return 0x00FF; }
inline static qint64 max() { return 0xFFFF; }
inline static qint64 min() { return 0; }
inline static qint8 bits() { return 16; }
};
......@@ -64,7 +62,7 @@ template<>
class KoColorSpaceMathsTraits<quint32> {
public:
typedef qint64 compositetype;
inline static qint64 max() { return 0xFFFF; }
inline static qint64 max() { return 0xFFFFFFFF; }
inline static qint64 min() { return 0; }
inline static qint8 bits() { return 32; }
};
......@@ -75,9 +73,17 @@ class KoColorSpaceMaths {
typedef KoColorSpaceMathsTraits<_T> traits;
typedef typename traits::compositetype traits_compositetype;
public:
inline static _T multiply(_T a, _Tdst b)
{
return ((traits_compositetype)a * b ) / KoColorSpaceMathsTraits<_Tdst>::max();
}
inline static _T divide(_T a, _Tdst b)
{
return ((traits_compositetype)a * KoColorSpaceMathsTraits<_Tdst>::max() ) / b;
}
inline static _T blend(_T a, _T b, qint64 alpha)
{
traits_compositetype c = ((traits_compositetype)a - (traits_compositetype)b) >> traits::bits();
traits_compositetype c = ( ((traits_compositetype)a - (traits_compositetype)b) * alpha ) >> traits::bits();
return c+b;
}
/**
......@@ -87,10 +93,6 @@ class KoColorSpaceMaths {
{
return (traits_compositetype)a >> ( traits::bits() - KoColorSpaceMathsTraits<_Tdst>::bits() );
}
inline static _T multiply(_T a, _T b)
{
return a * b / traits::max();
}
};
......
......@@ -38,7 +38,7 @@
#include "KoColorSpaceRegistry.h"
#include "colorspaces/KoAlphaColorSpace.h"
#include "colorspaces/KoLabColorSpace.h"
#include "colorspaces/KoRgbU32ColorSpace.h"
#include "colorspaces/KoRgbU16ColorSpace.h"
KoColorSpaceRegistry *KoColorSpaceRegistry::m_singleton = 0;
......@@ -100,7 +100,7 @@ void KoColorSpaceRegistry::init()
KoColorProfile *labProfile = new KoColorProfile(cmsCreateLabProfile(NULL));
addProfile(labProfile);
add(new KoLabColorSpaceFactory());
add(new KoRgbU32ColorSpaceFactory());
add(new KoRgbU16ColorSpaceFactory());
/* XXX where to put this
KisHistogramProducerFactoryRegistry::instance()->add(
new KisBasicHistogramProducerFactory<KisBasicU16HistogramProducer>
......
/*
* Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KOCOMPOSITEOPIMPL_H_
#define KOCOMPOSITEOPIMPL_H_
#include "KoColorSpaceMaths.h"
#include "KoCompositeOp.h"
#define NATIVE_OPACITY_OPAQUE KoColorSpaceMathsTraits<channels_type>::max()
#define NATIVE_OPACITY_TRANSPARENT KoColorSpaceMathsTraits<channels_type>::min()
#if 1
template<class _CSTraits>
class CompositeOver : public KoCompositeOp {
typedef typename _CSTraits::channels_type channels_type;
public:
CompositeOver(KoColorSpace * cs)
: KoCompositeOp(cs, COMPOSITE_OVER, i18n("Normal" ) )
{
}
public:
struct Pixel {
quint16 lightness;
quint16 a;
quint16 b;
quint16 alpha;
};
void composite(quint8 *dstRowStart,
qint32 dststride,
const quint8 *srcRowStart,
qint32 srcstride,
const quint8 *maskRowStart,
qint32 maskstride,
qint32 rows,
qint32 cols,
quint8 U8_opacity,
const QBitArray & channelFlags) const
{
Q_UNUSED( channelFlags );
channels_type opacity = KoColorSpaceMaths<quint8, channels_type>::scaleToA(U8_opacity);
qint32 pixelSize = colorSpace()->pixelSize();
while (rows > 0) {
const channels_type *srcN = reinterpret_cast<const channels_type *>(srcRowStart);
channels_type *dstN = reinterpret_cast<channels_type *>(dstRowStart);
const quint8 *mask = maskRowStart;
qint32 columns = cols;
while (columns > 0) {
channels_type srcAlpha = srcN[_CSTraits::alpha_pos];
// apply the alphamask
if (mask != 0) {
if (*mask != OPACITY_OPAQUE) {
srcAlpha = KoColorSpaceMaths<channels_type,quint8>::multiply(srcAlpha, *mask);
}
mask++;
}
if (srcAlpha != NATIVE_OPACITY_TRANSPARENT) {
if (opacity != NATIVE_OPACITY_OPAQUE) {
srcAlpha = KoColorSpaceMaths<channels_type>::multiply(srcAlpha, opacity);
}
if (srcAlpha == NATIVE_OPACITY_OPAQUE) {
memcpy(dstN, srcN, pixelSize);
} else {
channels_type dstAlpha = dstN[_CSTraits::alpha_pos];
channels_type srcBlend;
if (dstAlpha == NATIVE_OPACITY_OPAQUE) {
srcBlend = srcAlpha;
} else {
channels_type newAlpha = dstAlpha + KoColorSpaceMaths<channels_type>::multiply(NATIVE_OPACITY_OPAQUE - dstAlpha, srcAlpha);
dstN[_CSTraits::alpha_pos] = newAlpha;
if (newAlpha != 0) {
srcBlend = KoColorSpaceMaths<channels_type>::divide(srcAlpha, newAlpha);
} else {
srcBlend = srcAlpha;
}
}
if (srcBlend == NATIVE_OPACITY_OPAQUE) {
memcpy(dstN, srcN, pixelSize);
} else {
for(uint i = 0; i < _CSTraits::channels_nb; i++)
{
if(i != _CSTraits::alpha_pos)
dstN[i] = KoColorSpaceMaths<channels_type>::blend(srcN[i], dstN[i], srcBlend);
}
}
}
}
columns--;
srcN+=_CSTraits::channels_nb;
dstN+=_CSTraits::channels_nb;
}
rows--;
srcRowStart += srcstride;
dstRowStart += dststride;
if(maskRowStart) {
maskRowStart += maskstride;
}
}
}
};
#endif
#endif
......@@ -22,8 +22,6 @@
#ifndef KOLCMSCOLORSPACE_H_
#define KOLCMSCOLORSPACE_H_
#include <Q3MemArray>
#include <kconfig.h>
#include <kglobal.h>
......@@ -86,7 +84,7 @@ class KoLcmsColorSpace : public KoColorSpaceAbstract<_CSTraits> {
m_qcolordata = new quint8[3];
Q_CHECK_PTR(m_qcolordata);
if (m_profile == 0) return;
if (m_profile == 0) { exit(0); return; }
// For conversions from default rgb
m_lastFromRGB = cmsCreate_sRGBProfile();
......@@ -99,6 +97,14 @@ class KoLcmsColorSpace : public KoColorSpaceAbstract<_CSTraits> {
m_lastFromRGB, TYPE_BGR_8,
INTENT_PERCEPTUAL, 0);
m_defaultFromRGB16 = cmsCreateTransform(m_lastFromRGB, TYPE_BGR_16,
m_profile->profile(), m_cmType,
INTENT_PERCEPTUAL, 0);
m_defaultToRGB16 = cmsCreateTransform(m_profile->profile(), m_cmType,
m_lastFromRGB, TYPE_BGR_16,
INTENT_PERCEPTUAL, 0);
cmsHPROFILE hLab = cmsCreateLabProfile(NULL);
m_defaultFromLab = cmsCreateTransform(hLab, TYPE_Lab_16, m_profile->profile(), m_cmType,
......@@ -205,13 +211,38 @@ class KoLcmsColorSpace : public KoColorSpaceAbstract<_CSTraits> {
cmsDoTransform( m_defaultFromLab, const_cast<quint8 *>( src ), dst, nPixels );
}
virtual void fromRgbA16(const quint8 * src, quint8 * dst, const quint32 nPixels) const
{
if ( m_defaultFromRGB16 == 0 ) return;
cmsDoTransform( m_defaultFromRGB16, const_cast<quint8 *>( src ), dst, nPixels );
}
virtual void toRgbA16(const quint8 * src, quint8 * dst, const quint32 nPixels) const
{
if ( m_defaultToRGB16 == 0 ) return;
cmsDoTransform( m_defaultToRGB16, const_cast<quint8 *>( src ), dst, nPixels );
}
virtual bool convertPixelsTo(const quint8 * src,
quint8 * dst,
KoColorSpace * dstColorSpace,
quint32 numPixels,
qint32 renderingIntent)
{
/* kdDebug() << "new conversion" << endl;
for(int i = 0; i < numPixels; i++)
{
typename _CSTraits::channels_type* srcNative = this->nativeArray( const_cast<quint8*>( src + i * this->pixelSize()) );
kdDebug() << this->pixelSize() << dstColorSpace->pixelSize() << " " << srcNative[0] << " " << srcNative[1] << " " << srcNative[2] << " " << srcNative[3] << endl;
srcNative[0] = 0xFFF0;
srcNative[1] = 0x5FFF;
srcNative[2] = 0x2FFF;
srcNative[3] = 0xFFFF;
kdDebug() << srcNative[0] << " " << srcNative[1] << " " << srcNative[2] << " " << srcNative[3] << endl;
}*/
if (dstColorSpace->colorSpaceType() == colorSpaceType()
&& dstColorSpace->getProfile() == getProfile())
{
......@@ -394,16 +425,15 @@ class KoLcmsColorSpace : public KoColorSpaceAbstract<_CSTraits> {
virtual void invertColor(quint8 * src, qint32 nPixels)
{
QColor c;
quint8 opacity;
quint16 rgba[4];
quint32 psize = this->pixelSize();
while (nPixels--)
while(nPixels--)
{
toQColor(src, &c, &opacity);
c.setRgb(UINT8_MAX - c.red(), UINT8_MAX - c.green(), UINT8_MAX - c.blue());
fromQColor( c, opacity, src);
toRgbA16(src, reinterpret_cast<quint8 *>(rgba), 1);
rgba[0] = KoColorSpaceMathsTraits<quint16>::max() - rgba[0];
rgba[1] = KoColorSpaceMathsTraits<quint16>::max() - rgba[1];
rgba[2] = KoColorSpaceMathsTraits<quint16>::max() - rgba[2];
fromRgbA16(reinterpret_cast<quint8 *>(rgba), src, 1);
src += psize;
}
}
......@@ -553,6 +583,8 @@ class KoLcmsColorSpace : public KoColorSpaceAbstract<_CSTraits> {
quint8 * m_qcolordata; // A small buffer for conversion from and to qcolor.
cmsHTRANSFORM m_defaultToRGB; // Default transform to 8 bit sRGB
cmsHTRANSFORM m_defaultFromRGB; // Default transform from 8 bit sRGB
cmsHTRANSFORM m_defaultToRGB16; // Default transform to 16 bit sRGB
cmsHTRANSFORM m_defaultFromRGB16; // Default transform from 16 bit sRGB
cmsHPROFILE m_lastRGBProfile; // Last used profile to transform to/from RGB
cmsHTRANSFORM m_lastToRGB; // Last used transform to transform to RGB
......@@ -572,7 +604,6 @@ class KoLcmsColorSpace : public KoColorSpaceAbstract<_CSTraits> {
typedef QMap<KoColorSpace *, cmsHTRANSFORM> TransformMap;
TransformMap m_transforms; // Cache for existing transforms
Q3MemArray<quint8> m_conversionCache; // XXX: This will be a bad problem when we have threading.
};
......
......@@ -213,7 +213,7 @@ private:
KoLcmsColorSpaceTrait(const KoLcmsColorSpaceTrait&);
KoLcmsColorSpaceTrait& operator=(const KoLcmsColorSpaceTrait&);
Q3MemArray<quint8> m_conversionCache; // XXX: This will be a bad problem when we have threading.
// Q3MemArray<quint8> m_conversionCache; // XXX: This will be a bad problem when we have threading.
};
#endif // KIS_LCMS_BASE_COLORSPACE_H_
......@@ -17,26 +17,28 @@
* Boston, MA 02110-1301, USA.
*/
#include "KoRgbU32ColorSpace.h"
#include "KoRgbU16ColorSpace.h"
#include <kdebug.h>
#include <klocale.h>
#include "KoCompositeOp.h"
#include "KoCompositeOpImpl.h"
KoRgbU32ColorSpace::KoRgbU32ColorSpace(KoColorSpaceRegistry * parent, KoColorProfile *p) :
KoLcmsColorSpace<RgbU32Traits>("RGBU32", i18n("RGB 32-bit integer/channel)"), parent, TYPE_BGRA_32, icSigRgbData, p)
KoRgbU16ColorSpace::KoRgbU16ColorSpace(KoColorSpaceRegistry * parent, KoColorProfile *p) :
KoLcmsColorSpace<RgbU16Traits>("RGBU16", i18n("RGB 16-bit integer/channel)"), parent, TYPE_BGRA_16, icSigRgbData, p)
{
m_channels.push_back(new KoChannelInfo(i18n("Red"), 2, KoChannelInfo::COLOR, KoChannelInfo::UINT32, 4, QColor(255,0,0)));
m_channels.push_back(new KoChannelInfo(i18n("Green"), 1, KoChannelInfo::COLOR, KoChannelInfo::UINT32, 4, QColor(0,255,0)));
m_channels.push_back(new KoChannelInfo(i18n("Blue"), 0, KoChannelInfo::COLOR, KoChannelInfo::UINT32, 4, QColor(0,0,255)));
m_channels.push_back(new KoChannelInfo(i18n("Alpha"), 3, KoChannelInfo::ALPHA, KoChannelInfo::UINT8));
m_channels.push_back(new KoChannelInfo(i18n("Red"), 2, KoChannelInfo::COLOR, KoChannelInfo::UINT16, 4, QColor(255,0,0)));
m_channels.push_back(new KoChannelInfo(i18n("Green"), 1, KoChannelInfo::COLOR, KoChannelInfo::UINT16, 4, QColor(0,255,0)));
m_channels.push_back(new KoChannelInfo(i18n("Blue"), 0, KoChannelInfo::COLOR, KoChannelInfo::UINT16, 4, QColor(0,0,255)));
m_channels.push_back(new KoChannelInfo(i18n("Alpha"), 3, KoChannelInfo::ALPHA, KoChannelInfo::UINT16));