Commit 7c246797 authored by Torsten Rahn's avatar Torsten Rahn
Browse files

Adding InvertColorBlending and InvertHueBlending which operate on a single texture layer

and allow for a dark mode:

        <texture name="mapnik_data" expire="604800">
          <sourcedir format="PNG"> earth/openstreetmap </sourcedir>
          <tileSize width="256" height="256"/>
          <storageLayout levelZeroColumns="1" levelZeroRows="1" maximumTileLevel="19" mode="OpenStreetMap"/>
          <projection name="Mercator"/>
          <blending name="InvertColorBlending"/>
        </texture>
parent 14180464
Pipeline #259994 passed with stage
in 19 minutes and 6 seconds
......@@ -51,6 +51,55 @@ void GrayscaleBlending::blend( QImage * const bottom, TextureTile const * const
}
void InvertColorBlending::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 );
QImage const topImagePremult = top->image()->convertToFormat( QImage::Format_ARGB32_Premultiplied );
// Draw an inverted version of the bottom image
int const width = bottom->width();
int const height = bottom->height();
for ( int y = 0; y < height; ++y ) {
for ( int x = 0; x < width; ++x ) {
QRgb const topPixel = topImagePremult.pixel( x, y );
QRgb const invertedPixel = qRgb( 255 - qRed(topPixel), 255 - qGreen(topPixel), 255 - qBlue(topPixel) );
bottom->setPixel( x, y, invertedPixel );
}
}
}
void InvertHueBlending::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 );
QImage const topImagePremult = top->image()->convertToFormat( QImage::Format_ARGB32_Premultiplied );
// Draw an inverted version of the bottom image
int const width = bottom->width();
int const height = bottom->height();
for ( int y = 0; y < height; ++y ) {
for ( int x = 0; x < width; ++x ) {
QRgb const topPixel = topImagePremult.pixel( x, y );
QColor invertedColor(255 - qRed(topPixel), 255 - qGreen(topPixel), 255 - qBlue(topPixel));
int hue = invertedColor.hslHue();
int saturation = invertedColor.hslSaturation();
int lightness = invertedColor.lightness();
QColor naturalInvertedColor = QColor::fromHsl((hue + 195) % 255 , saturation, lightness);
QRgb naturalInvertedPixel = naturalInvertedColor.rgb();
bottom->setPixel( x, y, naturalInvertedPixel );
}
}
}
// pre-conditions:
// - bottom and top image have the same size
// - bottom image format is ARGB32_Premultiplied
......
......@@ -242,6 +242,18 @@ class GrayscaleBlending: public Blending
void blend( QImage * const bottom, TextureTile const * const top ) const override;
};
class InvertColorBlending: public Blending
{
public:
void blend( QImage * const bottom, TextureTile const * const top ) const override;
};
class InvertHueBlending: public Blending
{
public:
void blend( QImage * const bottom, TextureTile const * const top ) const override;
};
}
#endif
......@@ -77,6 +77,8 @@ BlendingFactory::BlendingFactory( const SunLocator *sunLocator )
m_blendings.insert( "CloudsBlending", new CloudsBlending );
m_blendings.insert( "SunLightBlending", m_sunLightBlending );
m_blendings.insert( "GrayscaleBlending", new GrayscaleBlending );
m_blendings.insert( "InvertColorBlending", new InvertColorBlending );
m_blendings.insert( "InvertHueBlending", new InvertHueBlending );
}
BlendingFactory::~BlendingFactory()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment