<commit_before>// Copyright 2010 <NAME> <<EMAIL>>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library. If not, see <http://www.gnu.org/licenses/>.

#include "BlendingAlgorithms.h"

#include "TextureTile.h"

#include <cmath>

#include <QtGui/QImage>
#include <QtGui/QPainter>

namespace Marble
{

void OverpaintBlending::blend( QImage * const bottom, TextureTile const * const top ) const
{
    Q_ASSERT( bottom );
    Q_ASSERT( top );
    Q_ASSERT( top->image() );
    Q_ASSERT( bottom->size() == top->image()->size() );
    Q_ASSERT( bottom->format() == QImage::Format_ARGB32_Premultiplied );

    QPainter painter( bottom );

    painter.drawImage( 0, 0, *top->image() );
}

// pre-conditions:
// - bottom and top image have the same size
// - bottom image format is ARGB32_Premultiplied
void IndependentChannelBlending::blend( QImage * const bottom,
                                        TextureTile const * const top ) const
{
    QImage const * const topImage = top->image();
    Q_ASSERT( topImage );
    Q_ASSERT( bottom->size() == topImage->size() );
    Q_ASSERT( bottom->format() == QImage::Format_ARGB32_Premultiplied );

    int const width = bottom->width();
    int const height = bottom->height();
    QImage const topImagePremult = topImage->convertToFormat( QImage::Format_ARGB32_Premultiplied );
    for ( int y = 0; y < height; ++y ) {
        for ( int x = 0; x < width; ++x ) {
            QRgb const bottomPixel = bottom->pixel( x, y );
            QRgb const topPixel = topImagePremult.pixel( x, y );
            qreal const resultRed = blendChannel( qRed( bottomPixel ) / 255.0,
                                                  qRed( topPixel ) / 255.0 );
            qreal const resultGreen = blendChannel( qGreen( bottomPixel ) / 255.0,
                                                    qGreen( topPixel ) / 255.0 );
            qreal const resultBlue = blendChannel( qBlue( bottomPixel ) / 255.0,
                                                   qBlue( topPixel ) / 255.0 );
            bottom->setPixel( x, y, qRgb( resultRed * 255.0,
                                          resultGreen * 255.0,
                                          resultBlue * 255.0 ));
        }
    }
}


// Neutral blendings

qreal AllanonBlending::blendChannel( qreal const bottomColorIntensity,
                                     qreal const topColorIntensity ) const
{
    return ( bottomColorIntensity + topColorIntensity ) / 2.0;
}

qreal ArcusTangentBlending::blendChannel( qreal const bottomColorIntensity,
                                          qreal const topColorIntensity ) const
{
    return 2.0 * atan( topColorIntensity / bottomColorIntensity ) / M_PI;
}

qreal GeometricMeanBlending::blendChannel( qreal const bottomColorIntensity,
                                           qreal const topColorIntensity ) const
{
    return sqrt( bottomColorIntensity * topColorIntensity );
}

qreal LinearLightBlending::blendChannel( qreal const bottomColorIntensity,
                                         qreal const topColorIntensity ) const
{
    return qMin( qreal( 1.0 ),
                 qMax( qreal( 0.0 ), qreal( bottomColorIntensity + 2.0 * topColorIntensity - 1.0 )));
}

qreal OverlayBlending::blendChannel( qreal const bottomColorIntensity,
                                     qreal const topColorIntensity ) const
{
    if ( bottomColorIntensity < 0.5 )
        return 2.0 * bottomColorIntensity * topColorIntensity;
    else
        return 1.0 - 2.0 * ( 1.0 - bottomColorIntensity ) * ( 1.0 - topColorIntensity );
}

qreal ParallelBlending::blendChannel( qreal const bottomColorIntensity,
                                      qreal const topColorIntensity ) const
{
    Q_UNUSED(bottomColorIntensity);
    Q_UNUSED(topColorIntensity);
    // FIXME:    return qMin( qMax( 2.0 / ( 1.0 / bottomColorIntensity + 1.0 / topColorIntensity )), 0.0, 1.0 );
    return 0.0;
}

qreal TextureBlending::blendChannel( qreal const bottomColorIntensity,
                                     qreal const topColorIntensity ) const
{
    Q_UNUSED(bottomColorIntensity);
    Q_UNUSED(topColorIntensity);
    // FIXME: return qMax( qMin( topColorIntensity + bottomColorIntensity ) - 0.5 ), 1.0 ), 0.0 );
    return 0.0;
}


// Darkening blendings

qreal ColorBurnBlending::blendChannel( qreal const bottomColorIntensity,
                                       qreal const topColorIntensity ) const
{
    Q_UNUSED(bottomColorIntensity);
    Q_UNUSED(topColorIntensity);
    // FIXME: check if this formula makes sense
    return qMin( qreal( 1.0 ),
                 qMax( qreal( 0.0 ), qreal( 1.0 - ( 1.0 - bottomColorIntensity ) / topColorIntensity )));
}

qreal DarkBlending::blendChannel( qreal const bottomColorIntensity,
                                  qreal const topColorIntensity ) const
{
    return ( bottomColorIntensity + 1.0 - topColorIntensity ) * topColorIntensity;
}

qreal DarkenBlending::blendChannel( qreal const bottomColorIntensity,
                                    qreal const topColorIntensity ) const
{
    // FIXME: is this really ok? not vice versa?
    return bottomColorIntensity > topColorIntensity ? topColorIntensity : bottomColorIntensity;
}

qreal DivideBlending::blendChannel( qreal const bottomColorIntensity,
                                    qreal const topColorIntensity ) const
{
    return log( 1.0  + bottomColorIntensity / ( 1.0  - topColorIntensity ) / 8.0) / log(2.0);
}

qreal GammaDarkBlending::blendChannel( qreal const bottomColorIntensity,
                                       qreal const topColorIntensity ) const
{
    return pow( bottomColorIntensity, 1.0 / topColorIntensity );
}

qreal LinearBurnBlending::blendChannel( qreal const bottomColorIntensity,
                                        qreal const topColorIntensity ) const
{
    return qMax( qreal(0.0), bottomColorIntensity + topColorIntensity - 1.0 );
}

qreal MultiplyBlending::blendChannel( qreal const bottomColorIntensity,
                                      qreal const topColorIntensity ) const
{
    return bottomColorIntensity * topColorIntensity;
}

qreal SubtractiveBlending::blendChannel( qreal const bottomColorIntensity,
                                         qreal const topColorIntensity ) const
{
    return qMax( bottomColorIntensity - topColorIntensity, qreal(0.0) );
}


// Lightening blendings

qreal AdditiveBlending::blendChannel( qreal const bottomColorIntensity,
                                      qreal const topColorIntensity ) const
{
    return qMin( topColorIntensity + bottomColorIntensity, qreal(1.0) );<commit_msg>fix compilation on Maemo<commit_after>// Copyright 2010 <NAME> <<EMAIL>>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library. If not, see <http://www.gnu.org/licenses/>.

#include "BlendingAlgorithms.h"

#include "TextureTile.h"

#include <cmath>

#include <QtGui/QImage>
#include <QtGui/QPainter>

namespace Marble
{

void OverpaintBlending::blend( QImage * const bottom, TextureTile const * const top ) const
{
    Q_ASSERT( bottom );
    Q_ASSERT( top );
    Q_ASSERT( top->image() );
    Q_ASSERT( bottom->size() == top->image()->size() );
    Q_ASSERT( bottom->format() == QImage::Format_ARGB32_Premultiplied );

    QPainter painter( bottom );

    painter.drawImage( 0, 0, *top->image() );
}

// pre-conditions:
// - bottom and top image have the same size
// - bottom image format is ARGB32_Premultiplied
void IndependentChannelBlending::blend( QImage * const bottom,
                                        TextureTile const * const top ) const
{
    QImage const * const topImage = top->image();
    Q_ASSERT( topImage );
    Q_ASSERT( bottom->size() == topImage->size() );
    Q_ASSERT( bottom->format() == QImage::Format_ARGB32_Premultiplied );

    int const width = bottom->width();
    int const height = bottom->height();
    QImage const topImagePremult = topImage->convertToFormat( QImage::Format_ARGB32_Premultiplied );
    for ( int y = 0; y < height; ++y ) {
        for ( int x = 0; x < width; ++x ) {
            QRgb const bottomPixel = bottom->pixel( x, y );
            QRgb const topPixel = topImagePremult.pixel( x, y );
            qreal const resultRed = blendChannel( qRed( bottomPixel ) / 255.0,
                                                  qRed( topPixel ) / 255.0 );
            qreal const resultGreen = blendChannel( qGreen( bottomPixel ) / 255.0,
                                                    qGreen( topPixel ) / 255.0 );
            qreal const resultBlue = blendChannel( qBlue( bottomPixel ) / 255.0,
                                                   qBlue( topPixel ) / 255.0 );
            bottom->setPixel( x, y, qRgb( resultRed * 255.0,
                                          resultGreen * 255.0,
                                          resultBlue * 255.0 ));
        }
    }
}


// Neutral blendings

qreal AllanonBlending::blendChannel( qreal const bottomColorIntensity,
                                     qreal const topColorIntensity ) const
{
    return ( bottomColorIntensity + topColorIntensity ) / 2.0;
}

qreal ArcusTangentBlending::blendChannel( qreal const bottomColorIntensity,
                                          qreal const topColorIntensity ) const
{
    return 2.0 * atan( topColorIntensity / bottomColorIntensity ) / M_PI;
}

qreal GeometricMeanBlending::blendChannel( qreal const bottomColorIntensity,
                                           qreal const topColorIntensity ) const
{
    return sqrt( bottomColorIntensity * topColorIntensity );
}

qreal LinearLightBlending::blendChannel( qreal const bottomColorIntensity,
                                         qreal const topColorIntensity ) const
{
    return qMin( qreal( 1.0 ),
                 qMax( qreal( 0.0 ), qreal( bottomColorIntensity + 2.0 * topColorIntensity - 1.0 )));
}

qreal OverlayBlending::blendChannel( qreal const bottomColorIntensity,
                                     qreal const topColorIntensity ) const
{
    if ( bottomColorIntensity < 0.5 )
        return 2.0 * bottomColorIntensity * topColorIntensity;
    else
        return 1.0 - 2.0 * ( 1.0 - bottomColorIntensity ) * ( 1.0 - topColorIntensity );
}

qreal ParallelBlending::blendChannel( qreal const bottomColorIntensity,
                                      qreal const topColorIntensity ) const
{
    Q_UNUSED(bottomColorIntensity);
    Q_UNUSED(topColorIntensity);
    // FIXME:    return qMin( qMax( 2.0 / ( 1.0 / bottomColorIntensity + 1.0 / topColorIntensity )), 0.0, 1.0 );
    return 0.0;
}

qreal TextureBlending::blendChannel( qreal const bottomColorIntensity,
                                     qreal const topColorIntensity ) const
{
    Q_UNUSED(bottomColorIntensity);
    Q_UNUSED(topColorIntensity);
    // FIXME: return qMax( qMin( topColorIntensity + bottomColorIntensity ) - 0.5 ), 1.0 ), 0.0 );
    return 0.0;
}


// Darkening blendings

qreal ColorBurnBlending::blendChannel( qreal const bottomColorIntensity,
                                       qreal const topColorIntensity ) const
{
    Q_UNUSED(bottomColorIntensity);
    Q_UNUSED(topColorIntensity);
    // FIXME: check if this formula makes sense
    return qMin( qreal( 1.0 ),
                 qMax( qreal( 0.0 ), qreal( 1.0 - ( 1.0 - bottomColorIntensity ) / topColorIntensity )));
}

qreal DarkBlending::blendChannel( qreal const bottomColorIntensity,
                                  qreal const topColorIntensity ) const
{
    return ( bottomColorIntensity + 1.0 - topColorIntensity ) * topColorIntensity;
}

qreal DarkenBlending::blendChannel( qreal const bottomColorIntensity,
                                    qreal const topColorIntensity ) const
{
    // FIXME: is this really ok? not vice versa?
    return bottomColorIntensity > topColorIntensity ? topColorIntensity : bottomColorIntensity;
}

qreal DivideBlending::blendChannel( qreal const bottomColorIntensity,
                                    qreal const topColorIntensity ) const
{
    return log( 1.0  + bottomColorIntensity / ( 1.0  - topColorIntensity ) / 8.0) / log(2.0);
}

qreal GammaDarkBlending::blendChannel( qreal const bottomColorIntensity,
                                       qreal const topColorIntensity ) const
{
    return pow( bottomColorIntensity, 1.0 / topColorIntensity );
}

qreal LinearBurnBlending::blendChannel( qreal const bottomColorIntensity,
                                        qreal const topColorIntensity ) const
{
    return qMax( qreal(0.0), bottomColorIntensity + topColorIntensity - qreal( 1.0 ) );
}

qreal MultiplyBlending::blendChannel( qreal const bottomColorIntensity,
                                      qreal const topColorIntensity ) const
{
    return bottomColorIntensity * topColorIntensity;
}

qreal SubtractiveBlending::blendChannel( qreal const bottomColorIntensity,
                                         qreal const topColorIntensity ) const
{
    return qMax( bottomColorIntensity - topColorIntensity, qreal(0.0) );
}


// Lightening blendings

qreal AdditiveBlending::blendChannel( qreal const bottomColorIntensity,
                                      qreal const topColorIntensity ) const
{
    return qMin( topColorIntensity + bottomColorIntensity, qreal(1.0) );
{'fraction_non_alphanumeric': 0.08847707955970462, 'fraction_numerical': 0.017556081928382334, 'mean_word_length': 2.3060801473975125, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 62, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3212077', 'n_tokens_mistral': 4140, 'n_tokens_neox': 3940, 'n_words': 1112}