Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
QImage BlurEffect::processImage(const QImage &image, const KoFilterEffectRenderContext &context) const
{
    if (m_deviation.x() == 0.0 || m_deviation.y() == 0.0)
        return image;

    // TODO: take filter region into account
    // TODO: blur with different kernels in x and y
    // convert from bounding box coordinates
    QPointF dev = context.toUserSpace(m_deviation);
    // transform to view coordinates
    dev = context.viewConverter()->documentToView(dev);

    QImage result = image;
    fastbluralpha(result, dev.x());

    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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}