diff options
Diffstat (limited to 'chalk/chalkcolor/colorspaces/kis_alpha_colorspace.cpp')
-rw-r--r-- | chalk/chalkcolor/colorspaces/kis_alpha_colorspace.cpp | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/chalk/chalkcolor/colorspaces/kis_alpha_colorspace.cpp b/chalk/chalkcolor/colorspaces/kis_alpha_colorspace.cpp new file mode 100644 index 000000000..f7c1fbce3 --- /dev/null +++ b/chalk/chalkcolor/colorspaces/kis_alpha_colorspace.cpp @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <limits.h> +#include <stdlib.h> + +#include <tqimage.h> + +#include <kdebug.h> +#include <tdelocale.h> + +#include <config.h> + +#include LCMS_HEADER + +#include "kis_alpha_colorspace.h" +#include "kis_u8_base_colorspace.h" +#include "kis_channelinfo.h" +#include "kis_id.h" +#include "kis_integer_maths.h" + +namespace { + const TQ_UINT8 PIXEL_MASK = 0; +} + +KisAlphaColorSpace::KisAlphaColorSpace(KisColorSpaceFactoryRegistry * parent, + KisProfile *p) : + KisU8BaseColorSpace(KisID("ALPHA", i18n("Alpha mask")), TYPE_GRAY_8, icSigGrayData, parent, p) +{ + m_channels.push_back(new KisChannelInfo(i18n("Alpha"), i18n("A"), 0, KisChannelInfo::ALPHA, KisChannelInfo::UINT8)); + m_alphaPos = 0; +} + +KisAlphaColorSpace::~KisAlphaColorSpace() +{ +} + +void KisAlphaColorSpace::fromTQColor(const TQColor& /*c*/, TQ_UINT8 *dst, KisProfile * /*profile*/) +{ + dst[PIXEL_MASK] = OPACITY_OPAQUE; +} + +void KisAlphaColorSpace::fromTQColor(const TQColor& /*c*/, TQ_UINT8 opacity, TQ_UINT8 *dst, KisProfile * /*profile*/) +{ + dst[PIXEL_MASK] = opacity; +} + +void KisAlphaColorSpace::getAlpha(const TQ_UINT8 *pixel, TQ_UINT8 *alpha) const +{ + *alpha = *pixel; +} + +void KisAlphaColorSpace::toTQColor(const TQ_UINT8 */*src*/, TQColor *c, KisProfile * /*profile*/) +{ + c->setRgb(255, 255, 255); +} + +void KisAlphaColorSpace::toTQColor(const TQ_UINT8 *src, TQColor *c, TQ_UINT8 *opacity, KisProfile * /*profile*/) +{ + c->setRgb(255, 255, 255); + *opacity = src[PIXEL_MASK]; +} + +TQ_UINT8 KisAlphaColorSpace::difference(const TQ_UINT8 *src1, const TQ_UINT8 *src2) +{ + // Arithmetic operands smaller than int are converted to int automatically + return TQABS(src2[PIXEL_MASK] - src1[PIXEL_MASK]); +} + +void KisAlphaColorSpace::mixColors(const TQ_UINT8 **colors, const TQ_UINT8 *weights, TQ_UINT32 nColors, TQ_UINT8 *dst) const +{ + if (nColors > 0) { + TQ_UINT32 total = 0; + + while(nColors) + { + nColors--; + total += *colors[nColors] * weights[nColors]; + } + *dst = total / 255; + } +} + +TQValueVector<KisChannelInfo *> KisAlphaColorSpace::channels() const +{ + return m_channels; +} + +bool KisAlphaColorSpace::convertPixelsTo(const TQ_UINT8 *src, + TQ_UINT8 *dst, KisAbstractColorSpace * dstColorSpace, + TQ_UINT32 numPixels, + TQ_INT32 /*renderingIntent*/) +{ + // No lcms trickery here, we are only a opacity channel + TQ_INT32 size = dstColorSpace->pixelSize(); + + TQ_UINT32 j = 0; + TQ_UINT32 i = 0; + + while ( i < numPixels ) { + + dstColorSpace->fromTQColor(TQt::red, OPACITY_OPAQUE - *(src + i), (dst + j)); + + i += 1; + j += size; + + } + return true; + +} + + +//XXX bitblt of ColorSpaceAlpha does not take mask into consideration as this is probably not +// used ever +void KisAlphaColorSpace::bitBlt(TQ_UINT8 *dst, + TQ_INT32 dststride, + const TQ_UINT8 *src, + TQ_INT32 srcRowStride, + const TQ_UINT8 *srcAlphaMask, + TQ_INT32 maskRowStride, + TQ_UINT8 opacity, + TQ_INT32 rows, + TQ_INT32 cols, + const KisCompositeOp& op) +{ + + TQ_UINT8 *d; + const TQ_UINT8 *s; + TQ_INT32 i; + TQ_INT32 linesize; + + if (rows <= 0 || cols <= 0) + return; + switch (op.op()) { + case COMPOSITE_COPY: + compositeCopy(dst, dststride, src, srcRowStride, srcAlphaMask, maskRowStride, rows, cols, opacity); + return; + case COMPOSITE_CLEAR: + linesize = sizeof(TQ_UINT8) * cols; + d = dst; + while (rows-- > 0) { + memset(d, OPACITY_TRANSPARENT, linesize); + d += dststride; + } + return; + case COMPOSITE_ERASE: + while (rows-- > 0) { + d = dst; + s = src; + + for (i = cols; i > 0; i--, d ++, s ++) { + if (d[PIXEL_MASK] < s[PIXEL_MASK]) { + continue; + } + else { + d[PIXEL_MASK] = s[PIXEL_MASK]; + } + + } + + dst += dststride; + src += srcRowStride; + } + return; + case COMPOSITE_SUBTRACT: + while (rows-- > 0) { + d = dst; + s = src; + + for (i = cols; i > 0; i--, d++, s++) { + if (d[PIXEL_MASK] <= s[PIXEL_MASK]) { + d[PIXEL_MASK] = MIN_SELECTED; + } else { + d[PIXEL_MASK] -= s[PIXEL_MASK]; + } + } + + dst += dststride; + src += srcRowStride; + } + return; + case COMPOSITE_ALPHA_DARKEN: + while (rows-- > 0) { + d = dst; + s = src; + for (i = cols; i > 0; i--, d++, s++) { + if (s[PIXEL_MASK] == OPACITY_TRANSPARENT) + continue; + int srcAlpha = (s[PIXEL_MASK] * opacity + UINT8_MAX / 2) / UINT8_MAX; + if (srcAlpha > d[PIXEL_MASK]) + d[PIXEL_MASK] = srcAlpha; + } + dst += dststride; + src += srcRowStride; + } + return; + case COMPOSITE_OVER: + default: + if (opacity == OPACITY_TRANSPARENT) + return; + if (opacity != OPACITY_OPAQUE) { + while (rows-- > 0) { + d = dst; + s = src; + for (i = cols; i > 0; i--, d++, s++) { + if (s[PIXEL_MASK] == OPACITY_TRANSPARENT) + continue; + int srcAlpha = (s[PIXEL_MASK] * opacity + UINT8_MAX / 2) / UINT8_MAX; + d[PIXEL_MASK] = (d[PIXEL_MASK] * (UINT8_MAX - srcAlpha) + srcAlpha * UINT8_MAX + UINT8_MAX / 2) / UINT8_MAX; + } + dst += dststride; + src += srcRowStride; + } + } + else { + while (rows-- > 0) { + d = dst; + s = src; + for (i = cols; i > 0; i--, d++, s++) { + if (s[PIXEL_MASK] == OPACITY_TRANSPARENT) + continue; + if (d[PIXEL_MASK] == OPACITY_TRANSPARENT || s[PIXEL_MASK] == OPACITY_OPAQUE) { + memcpy(d, s, 1); + continue; + } + int srcAlpha = s[PIXEL_MASK]; + d[PIXEL_MASK] = (d[PIXEL_MASK] * (UINT8_MAX - srcAlpha) + srcAlpha * UINT8_MAX + UINT8_MAX / 2) / UINT8_MAX; + } + dst += dststride; + src += srcRowStride; + } + } + + } +} + +KisCompositeOpList KisAlphaColorSpace::userVisiblecompositeOps() const +{ + KisCompositeOpList list; + + list.append(KisCompositeOp(COMPOSITE_OVER)); + + return list; +} + +TQString KisAlphaColorSpace::channelValueText(const TQ_UINT8 *pixel, TQ_UINT32 channelIndex) const +{ + Q_ASSERT(channelIndex < nChannels()); + TQ_UINT32 channelPosition = m_channels[channelIndex]->pos(); + + return TQString().setNum(pixel[channelPosition]); +} + +TQString KisAlphaColorSpace::normalisedChannelValueText(const TQ_UINT8 *pixel, TQ_UINT32 channelIndex) const +{ + Q_ASSERT(channelIndex < nChannels()); + TQ_UINT32 channelPosition = m_channels[channelIndex]->pos(); + + return TQString().setNum(static_cast<float>(pixel[channelPosition]) / UINT8_MAX); +} + + +void KisAlphaColorSpace::convolveColors(TQ_UINT8** colors, TQ_INT32 * kernelValues, KisChannelInfo::enumChannelFlags channelFlags, TQ_UINT8 *dst, TQ_INT32 factor, TQ_INT32 offset, TQ_INT32 nColors) const +{ + TQ_INT32 totalAlpha = 0; + + while (nColors--) + { + TQ_INT32 weight = *kernelValues; + + if (weight != 0) { + totalAlpha += (*colors)[PIXEL_MASK] * weight; + } + colors++; + kernelValues++; + } + + if (channelFlags & KisChannelInfo::FLAG_ALPHA) { + dst[PIXEL_MASK] = CLAMP((totalAlpha/ factor) + offset, 0, TQ_UINT8_MAX); + } +} |