QImage GammaFilterEffect::processImage(const QImage& image, const KoFilterEffectRenderContext& context) const { if (m_gamma<=0) return image; QImage result = image.convertToFormat(QImage::Format_ARGB32); const int bottom = context.filterRegion().bottom(); const int left = context.filterRegion().left(); const int right = context.filterRegion().right(); const int width = result.width(); const QRgb *src = (const QRgb*)image.constBits(); QRgb *dst = (QRgb*)result.bits(); const int max = 255; const qreal invMax = 1.0/ max; const qreal invGamma = m_gamma > 0 && m_gamma <= 10.0 ? 1 / m_gamma : 1.0; for (int row = context.filterRegion().top(); row < bottom; ++row) { int index = row * width + left; for (int col = left; col < right; ++col, ++index) { const QRgb &s = src[index]; const int red = qPow(invMax * qRed(s), invGamma) * max; const int green = qPow(invMax * qGreen(s), invGamma) * max; const int blue = qPow(invMax * qBlue(s), invGamma) * max; const int alpha = qAlpha(s); dst[index] = qRgba(red, green, blue, alpha); } } return result; }
QImage ColoringFilterEffect::processImage(const QImage& image, const KoFilterEffectRenderContext& context) const { if (m_red==0 && m_green==0 && m_blue==0 && m_contrast==0 && m_luminance==0) return image; QImage result = image.convertToFormat(QImage::Format_ARGB32); const int bottom = context.filterRegion().bottom(); const int left = context.filterRegion().left(); const int right = context.filterRegion().right(); const int width = result.width(); const QRgb *src = (const QRgb*)image.constBits(); QRgb *dst = (QRgb*)result.bits(); const int max = 255; const int maxHalf = 128; const qreal slope = m_contrast >=0 ? (maxHalf / (maxHalf - m_contrast*(maxHalf -1))) : ((maxHalf + m_contrast*(maxHalf -1)) / maxHalf); const int redAdd = (1-slope) * maxHalf + (m_red + m_luminance) * max; const int greenAdd = (1-slope) * maxHalf + (m_green + m_luminance) * max; const int blueAdd = (1-slope) * maxHalf + (m_blue + m_luminance) * max; for (int row = context.filterRegion().top(); row < bottom; ++row) { int index = row * width + left; for (int col = left; col < right; ++col, ++index) { const QRgb &s = src[index]; const int red = slope * qRed(s) + redAdd; const int green = slope * qGreen(s) + greenAdd; const int blue = slope * qBlue(s) + blueAdd; const int alpha = qAlpha(s); dst[index] = qRgba(qBound(0, red, max), qBound(0, green, max), qBound(0, blue, max), alpha); } } return result; }
QImage FloodEffect::processImage(const QImage &image, const KoFilterEffectRenderContext &context) const { QImage result = image; QPainter painter(&result); painter.fillRect(context.filterRegion(), m_color); return result; }
QImage ImageEffect::processImage(const QImage &image, const KoFilterEffectRenderContext &context) const { QImage result(image.size(), QImage::Format_ARGB32_Premultiplied); result.fill(qRgba(0, 0, 0, 0)); QPainter p(&result); p.drawImage(context.filterRegion(), m_image); return result; }
QImage ComponentTransferEffect::processImage(const QImage &image, const KoFilterEffectRenderContext &context) const { QImage result = image; #if QT_VERSION >= 0x040700 const QRgb *src = (const QRgb*)image.constBits(); #else const QRgb *src = (const QRgb*)image.bits(); #endif QRgb *dst = (QRgb*)result.bits(); int w = result.width(); qreal sa, sr, sg, sb; qreal da, dr, dg, db; int pixel; const QRect roi = context.filterRegion().toRect(); const int minRow = roi.top(); const int maxRow = roi.bottom(); const int minCol = roi.left(); const int maxCol = roi.right(); for (int row = minRow; row <= maxRow; ++row) { for (int col = minCol; col <= maxCol; ++col) { pixel = row * w + col; const QRgb &s = src[pixel]; sa = fromIntColor[qAlpha(s)]; sr = fromIntColor[qRed(s)]; sg = fromIntColor[qGreen(s)]; sb = fromIntColor[qBlue(s)]; // the matrix is applied to non-premultiplied color values // so we have to convert colors by dividing by alpha value if (sa > 0.0 && sa < 1.0) { sr /= sa; sb /= sa; sg /= sa; } dr = transferChannel(ChannelR, sr); dg = transferChannel(ChannelG, sg); db = transferChannel(ChannelB, sb); da = transferChannel(ChannelA, sa); da *= 255.0; // set pre-multiplied color values on destination image dst[pixel] = qRgba(static_cast<quint8>(qBound(qreal(0.0), dr * da, qreal(255.0))), static_cast<quint8>(qBound(qreal(0.0), dg * da, qreal(255.0))), static_cast<quint8>(qBound(qreal(0.0), db * da, qreal(255.0))), static_cast<quint8>(qBound(qreal(0.0), da, qreal(255.0)))); } } return result; }
QImage MonoFilterEffect::processImage(const QImage& image, const KoFilterEffectRenderContext& context) const { QImage result = image; QRgb* pixel = reinterpret_cast<QRgb*>( result.bits() ); const int right = context.filterRegion().right(); const int bottom = context.filterRegion().bottom(); const int width = result.width(); for( int row = context.filterRegion().top(); row < bottom; ++row ) { for( int col = context.filterRegion().left(); col < right; ++col ){ const QRgb currentPixel = pixel[row * width + col]; const int red = qRed(currentPixel); const int green = qGreen(currentPixel); const int blue = qBlue(currentPixel); const int monoValue = ( (red * 11 + green * 16 + blue * 5) / 32 ) / 127 * 255; pixel[row * width + col] = qRgb(monoValue, monoValue, monoValue); } } return result; }
QImage ColorMatrixEffect::processImage(const QImage &image, const KoFilterEffectRenderContext &context) const { QImage result = image; QRgb *src = (QRgb*)image.bits(); QRgb *dst = (QRgb*)result.bits(); int w = result.width(); const qreal * m = m_matrix.data(); qreal sa, sr, sg, sb; qreal da, dr, dg, db; QRect roi = context.filterRegion().toRect(); for (int row = roi.top(); row < roi.bottom(); ++row) { for (int col = roi.left(); col < roi.right(); ++col) { const QRgb &s = src[row*w+col]; sa = fromIntColor[qAlpha(s)]; sr = fromIntColor[qRed(s)]; sg = fromIntColor[qGreen(s)]; sb = fromIntColor[qBlue(s)]; // the matrix is applied to non-premultiplied color values // so we have to convert colors by dividing by alpha value if (sa > 0.0 && sa < 1.0) { sr /= sa; sb /= sa; sg /= sa; } // apply matrix to color values dr = m[ 0] * sr + m[ 1] * sg + m[ 2] * sb + m[ 3] * sa + m[ 4]; dg = m[ 5] * sr + m[ 6] * sg + m[ 7] * sb + m[ 8] * sa + m[ 9]; db = m[10] * sr + m[11] * sg + m[12] * sb + m[13] * sa + m[14]; da = m[15] * sr + m[16] * sg + m[17] * sb + m[18] * sa + m[19]; // the new alpha value da *= 255.0; // set pre-multiplied color values on destination image dst[row*w+col] = qRgba(static_cast<quint8>(qBound(qreal(0.0), dr * da, qreal(255.0))), static_cast<quint8>(qBound(qreal(0.0), dg * da, qreal(255.0))), static_cast<quint8>(qBound(qreal(0.0), db * da, qreal(255.0))), static_cast<quint8>(qBound(qreal(0.0), da, qreal(255.0)))); } } return result; }
QImage CompositeEffect::processImages(const QVector<QImage> &images, const KoFilterEffectRenderContext &context) const { int imageCount = images.count(); if (!imageCount) return QImage(); QImage result = images[0]; if (images.count() != 2) { return result; } if (m_operation == Arithmetic) { const QRgb *src = (QRgb*)images[1].constBits(); QRgb *dst = (QRgb*)result.bits(); int w = result.width(); qreal sa, sr, sg, sb; qreal da, dr, dg, db; int pixel = 0; // TODO: do we have to calculate with non-premuliplied colors here ??? QRect roi = context.filterRegion().toRect(); for (int row = roi.top(); row < roi.bottom(); ++row) { for (int col = roi.left(); col < roi.right(); ++col) { pixel = row * w + col; const QRgb &s = src[pixel]; QRgb &d = dst[pixel]; sa = fromIntColor[qAlpha(s)]; sr = fromIntColor[qRed(s)]; sg = fromIntColor[qGreen(s)]; sb = fromIntColor[qBlue(s)]; da = fromIntColor[qAlpha(d)]; dr = fromIntColor[qRed(d)]; dg = fromIntColor[qGreen(d)]; db = fromIntColor[qBlue(d)]; da = m_k[0] * sa * da + m_k[1] * da + m_k[2] * sa + m_k[3]; dr = m_k[0] * sr * dr + m_k[1] * dr + m_k[2] * sr + m_k[3]; dg = m_k[0] * sg * dg + m_k[1] * dg + m_k[2] * sg + m_k[3]; db = m_k[0] * sb * db + m_k[1] * db + m_k[2] * sb + m_k[3]; da *= 255.0; // set pre-multiplied color values on destination image d = qRgba(static_cast<quint8>(qBound(qreal(0.0), dr * da, qreal(255.0))), static_cast<quint8>(qBound(qreal(0.0), dg * da, qreal(255.0))), static_cast<quint8>(qBound(qreal(0.0), db * da, qreal(255.0))), static_cast<quint8>(qBound(qreal(0.0), da, qreal(255.0)))); } } } else { QPainter painter(&result); switch (m_operation) { case CompositeOver: painter.setCompositionMode(QPainter::CompositionMode_DestinationOver); break; case CompositeIn: painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); break; case CompositeOut: painter.setCompositionMode(QPainter::CompositionMode_DestinationOut); break; case CompositeAtop: painter.setCompositionMode(QPainter::CompositionMode_DestinationAtop); break; case CompositeXor: painter.setCompositionMode(QPainter::CompositionMode_Xor); break; default: // no composition mode break; } painter.drawImage(context.filterRegion(), images[1], context.filterRegion()); } return result; }
QImage MorphologyEffect::processImage(const QImage &image, const KoFilterEffectRenderContext &context) const { QImage result = image; QPointF radius = context.toUserSpace(m_radius); const int rx = static_cast<int>(ceil(radius.x())); const int ry = static_cast<int>(ceil(radius.y())); const int w = result.width(); const int h = result.height(); // setup mask const int maskSize = (1+2*rx)*(1+2*ry); int * mask = new int[maskSize]; int index = 0; for (int y = -ry; y <= ry; ++y) { for (int x = -rx; x <= rx; ++x) { mask[index] = y*w+x; index++; } } int dstPixel, srcPixel; uchar s0, s1, s2, s3; #if QT_VERSION >= 0x040700 const uchar * src = image.constBits(); #else const uchar * src = image.bits(); #endif uchar * dst = result.bits(); const QRect roi = context.filterRegion().toRect(); const int minX = qMax(rx, roi.left()); const int maxX = qMin(w-rx, roi.right()); const int minY = qMax(ry, roi.top()); const int maxY = qMin(h-ry, roi.bottom()); const int defValue = m_operator == Erode ? 255 : 0; uchar * d = 0; for (int row = minY; row < maxY; ++row) { for (int col = minX; col < maxX; ++col) { dstPixel = row * w + col; s0 = s1 = s2 = s3 = defValue; for (int i = 0; i < maskSize; ++i) { srcPixel = dstPixel+mask[i]; const uchar *s = &src[4*srcPixel]; if (m_operator == Erode ) { s0 = qMin(s0, s[0]); s1 = qMin(s1, s[1]); s2 = qMin(s2, s[2]); s3 = qMin(s3, s[3]); } else { s0 = qMax(s0, s[0]); s1 = qMax(s1, s[1]); s2 = qMax(s2, s[2]); s3 = qMax(s3, s[3]); } } d = &dst[4*dstPixel]; d[0] = s0; d[1] = s1; d[2] = s2; d[3] = s3; } } delete [] mask; return result; }