• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • lib
  • marble
  • blendings
BlendingAlgorithms.cpp
Go to the documentation of this file.
1 // Copyright 2010 Jens-Michael Hoffmann <jmho@c-xx.com>
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library. If not, see <http://www.gnu.org/licenses/>.
15 
16 #include "BlendingAlgorithms.h"
17 
18 #include "TextureTile.h"
19 
20 #include <cmath>
21 
22 #include <QImage>
23 #include <QPainter>
24 
25 namespace Marble
26 {
27 
28 void OverpaintBlending::blend( QImage * const bottom, TextureTile const * const top ) const
29 {
30  Q_ASSERT( bottom );
31  Q_ASSERT( top );
32  Q_ASSERT( top->image() );
33  Q_ASSERT( bottom->size() == top->image()->size() );
34  Q_ASSERT( bottom->format() == QImage::Format_ARGB32_Premultiplied );
35 
36  QPainter painter( bottom );
37 
38  painter.drawImage( 0, 0, *top->image() );
39 }
40 
41 void GrayscaleBlending::blend( QImage * const bottom, TextureTile const * const top ) const
42 {
43  Q_ASSERT( bottom );
44  Q_ASSERT( top );
45  Q_ASSERT( top->image() );
46  Q_ASSERT( bottom->size() == top->image()->size() );
47  Q_ASSERT( bottom->format() == QImage::Format_ARGB32_Premultiplied );
48  QImage const topImagePremult = top->image()->convertToFormat( QImage::Format_ARGB32_Premultiplied );
49 
50  // Draw a grayscale version of the bottom image
51  int const width = bottom->width();
52  int const height = bottom->height();
53 
54  for ( int y = 0; y < height; ++y ) {
55  for ( int x = 0; x < width; ++x ) {
56  QRgb const topPixel = topImagePremult.pixel( x, y );
57  int const gray = qGray( topPixel );
58  QRgb const grayPixel = qRgb( gray, gray, gray );
59  bottom->setPixel( x, y,grayPixel );
60  }
61  }
62 
63 }
64 
65 // pre-conditions:
66 // - bottom and top image have the same size
67 // - bottom image format is ARGB32_Premultiplied
68 void IndependentChannelBlending::blend( QImage * const bottom,
69  TextureTile const * const top ) const
70 {
71  QImage const * const topImage = top->image();
72  Q_ASSERT( topImage );
73  Q_ASSERT( bottom->size() == topImage->size() );
74  Q_ASSERT( bottom->format() == QImage::Format_ARGB32_Premultiplied );
75 
76  int const width = bottom->width();
77  int const height = bottom->height();
78  QImage const topImagePremult = topImage->convertToFormat( QImage::Format_ARGB32_Premultiplied );
79  for ( int y = 0; y < height; ++y ) {
80  for ( int x = 0; x < width; ++x ) {
81  QRgb const bottomPixel = bottom->pixel( x, y );
82  QRgb const topPixel = topImagePremult.pixel( x, y );
83  qreal const resultRed = blendChannel( qRed( bottomPixel ) / 255.0,
84  qRed( topPixel ) / 255.0 );
85  qreal const resultGreen = blendChannel( qGreen( bottomPixel ) / 255.0,
86  qGreen( topPixel ) / 255.0 );
87  qreal const resultBlue = blendChannel( qBlue( bottomPixel ) / 255.0,
88  qBlue( topPixel ) / 255.0 );
89  bottom->setPixel( x, y, qRgb( resultRed * 255.0,
90  resultGreen * 255.0,
91  resultBlue * 255.0 ));
92  }
93  }
94 }
95 
96 
97 // Neutral blendings
98 
99 qreal AllanonBlending::blendChannel( qreal const bottomColorIntensity,
100  qreal const topColorIntensity ) const
101 {
102  return ( bottomColorIntensity + topColorIntensity ) / 2.0;
103 }
104 
105 qreal ArcusTangentBlending::blendChannel( qreal const bottomColorIntensity,
106  qreal const topColorIntensity ) const
107 {
108  return 2.0 * atan( topColorIntensity / bottomColorIntensity ) / M_PI;
109 }
110 
111 qreal GeometricMeanBlending::blendChannel( qreal const bottomColorIntensity,
112  qreal const topColorIntensity ) const
113 {
114  return sqrt( bottomColorIntensity * topColorIntensity );
115 }
116 
117 qreal LinearLightBlending::blendChannel( qreal const bottomColorIntensity,
118  qreal const topColorIntensity ) const
119 {
120  return qMin( qreal( 1.0 ),
121  qMax( qreal( 0.0 ), qreal( bottomColorIntensity + 2.0 * topColorIntensity - 1.0 )));
122 }
123 
124 qreal OverlayBlending::blendChannel( qreal const bottomColorIntensity,
125  qreal const topColorIntensity ) const
126 {
127  if ( bottomColorIntensity < 0.5 )
128  return 2.0 * bottomColorIntensity * topColorIntensity;
129  else
130  return 1.0 - 2.0 * ( 1.0 - bottomColorIntensity ) * ( 1.0 - topColorIntensity );
131 }
132 
133 qreal ParallelBlending::blendChannel( qreal const bottomColorIntensity,
134  qreal const topColorIntensity ) const
135 {
136  Q_UNUSED(bottomColorIntensity);
137  Q_UNUSED(topColorIntensity);
138  // FIXME: return qMin( qMax( 2.0 / ( 1.0 / bottomColorIntensity + 1.0 / topColorIntensity )), 0.0, 1.0 );
139  return 0.0;
140 }
141 
142 qreal TextureBlending::blendChannel( qreal const bottomColorIntensity,
143  qreal const topColorIntensity ) const
144 {
145  Q_UNUSED(bottomColorIntensity);
146  Q_UNUSED(topColorIntensity);
147  // FIXME: return qMax( qMin( topColorIntensity + bottomColorIntensity ) - 0.5 ), 1.0 ), 0.0 );
148  return 0.0;
149 }
150 
151 
152 // Darkening blendings
153 
154 qreal ColorBurnBlending::blendChannel( qreal const bottomColorIntensity,
155  qreal const topColorIntensity ) const
156 {
157  Q_UNUSED(bottomColorIntensity);
158  Q_UNUSED(topColorIntensity);
159  // FIXME: check if this formula makes sense
160  return qMin( qreal( 1.0 ),
161  qMax( qreal( 0.0 ), qreal( 1.0 - ( 1.0 - bottomColorIntensity ) / topColorIntensity )));
162 }
163 
164 qreal DarkBlending::blendChannel( qreal const bottomColorIntensity,
165  qreal const topColorIntensity ) const
166 {
167  return ( bottomColorIntensity + 1.0 - topColorIntensity ) * topColorIntensity;
168 }
169 
170 qreal DarkenBlending::blendChannel( qreal const bottomColorIntensity,
171  qreal const topColorIntensity ) const
172 {
173  // FIXME: is this really ok? not vice versa?
174  return bottomColorIntensity > topColorIntensity ? topColorIntensity : bottomColorIntensity;
175 }
176 
177 qreal DivideBlending::blendChannel( qreal const bottomColorIntensity,
178  qreal const topColorIntensity ) const
179 {
180  return log( 1.0 + bottomColorIntensity / ( 1.0 - topColorIntensity ) / 8.0) / log(2.0);
181 }
182 
183 qreal GammaDarkBlending::blendChannel( qreal const bottomColorIntensity,
184  qreal const topColorIntensity ) const
185 {
186  return pow( bottomColorIntensity, 1.0 / topColorIntensity );
187 }
188 
189 qreal LinearBurnBlending::blendChannel( qreal const bottomColorIntensity,
190  qreal const topColorIntensity ) const
191 {
192  return qMax( qreal(0.0), bottomColorIntensity + topColorIntensity - qreal( 1.0 ) );
193 }
194 
195 qreal MultiplyBlending::blendChannel( qreal const bottomColorIntensity,
196  qreal const topColorIntensity ) const
197 {
198  return bottomColorIntensity * topColorIntensity;
199 }
200 
201 qreal SubtractiveBlending::blendChannel( qreal const bottomColorIntensity,
202  qreal const topColorIntensity ) const
203 {
204  return qMax( bottomColorIntensity - topColorIntensity, qreal(0.0) );
205 }
206 
207 
208 // Lightening blendings
209 
210 qreal AdditiveBlending::blendChannel( qreal const bottomColorIntensity,
211  qreal const topColorIntensity ) const
212 {
213  return qMin( topColorIntensity + bottomColorIntensity, qreal(1.0) );
214 }
215 
216 qreal ColorDodgeBlending::blendChannel( qreal const bottomColorIntensity,
217  qreal const topColorIntensity ) const
218 {
219  return qMin( qreal( 1.0 ),
220  qMax( qreal( 0.0 ), qreal( bottomColorIntensity / ( 1.0 - topColorIntensity ))));
221 }
222 
223 qreal GammaLightBlending::blendChannel( qreal const bottomColorIntensity,
224  qreal const topColorIntensity ) const
225 {
226  return pow( bottomColorIntensity, topColorIntensity );
227 }
228 
229 qreal HardLightBlending::blendChannel( qreal const bottomColorIntensity,
230  qreal const topColorIntensity ) const
231 {
232  return topColorIntensity < 0.5
233  ? 2.0 * bottomColorIntensity * topColorIntensity
234  : 1.0 - 2.0 * ( 1.0 - bottomColorIntensity ) * ( 1.0 - topColorIntensity );
235 }
236 
237 qreal LightBlending::blendChannel( qreal const bottomColorIntensity,
238  qreal const topColorIntensity ) const
239 {
240  return bottomColorIntensity * ( 1.0 - topColorIntensity ) + pow( topColorIntensity, 2 );
241 }
242 
243 qreal LightenBlending::blendChannel( qreal const bottomColorIntensity,
244  qreal const topColorIntensity ) const
245 {
246  // is this ok?
247  return bottomColorIntensity < topColorIntensity ? topColorIntensity : bottomColorIntensity;
248 }
249 
250 qreal PinLightBlending::blendChannel( qreal const bottomColorIntensity,
251  qreal const topColorIntensity ) const
252 {
253  return qMax( qreal(0.0), qMax( qreal(2.0 + topColorIntensity - 1.0),
254  qMin( bottomColorIntensity, qreal(2.0 * topColorIntensity ))));
255 }
256 
257 qreal ScreenBlending::blendChannel( qreal const bottomColorIntensity,
258  qreal const topColorIntensity ) const
259 {
260  return 1.0 - ( 1.0 - bottomColorIntensity ) * ( 1.0 - topColorIntensity );
261 }
262 
263 qreal SoftLightBlending::blendChannel( qreal const bottomColorIntensity,
264  qreal const topColorIntensity ) const
265 {
266  return pow( bottomColorIntensity, pow( 2.0, ( 2.0 * ( 0.5 - topColorIntensity ))));
267 }
268 
269 qreal VividLightBlending::blendChannel( qreal const bottomColorIntensity,
270  qreal const topColorIntensity ) const
271 {
272  return topColorIntensity < 0.5
273  ? qMin( qreal( 1.0 ),
274  qMax( qreal( 0.0 ), qreal( 1.0 - ( 1.0 - bottomColorIntensity ) / ( 2.0 * topColorIntensity ))))
275  : qMin( qreal( 1.0 ),
276  qMax( qreal( 0.0 ), qreal( bottomColorIntensity / ( 2.0 * ( 1.0 - topColorIntensity )))));
277 }
278 
279 
280 // Inverter blendings
281 
282 qreal AdditiveSubtractiveBlending::blendChannel( qreal const bottomColorIntensity,
283  qreal const topColorIntensity ) const
284 {
285  Q_UNUSED(bottomColorIntensity);
286  Q_UNUSED(topColorIntensity);
287  // FIXME:
288  // return qMin( 1.0, qMax( 0.0, abs( bottomColorIntensity * bottomColorIntensity
289  // - topColorIntensity * topColorIntensity )));
290  return 0.0;
291 }
292 
293 qreal BleachBlending::blendChannel( qreal const bottomColorIntensity,
294  qreal const topColorIntensity ) const
295 {
296  // FIXME: "why this is the same formula as Screen Blending? Please correct.)"
297  return 1.0 - ( 1.0 - bottomColorIntensity ) * ( 1.0 - topColorIntensity );
298 }
299 
300 qreal DifferenceBlending::blendChannel( qreal const bottomColorIntensity,
301  qreal const topColorIntensity ) const
302 {
303  return qMax( qMin( qreal( 1.0 ), qreal( bottomColorIntensity - topColorIntensity + 0.5 )),
304  qreal( 0.0 ));
305 }
306 
307 qreal EquivalenceBlending::blendChannel( qreal const bottomColorIntensity,
308  qreal const topColorIntensity ) const
309 {
310  return 1.0 - abs( bottomColorIntensity - topColorIntensity );
311 }
312 
313 qreal HalfDifferenceBlending::blendChannel( qreal const bottomColorIntensity,
314  qreal const topColorIntensity ) const
315 {
316  return bottomColorIntensity + topColorIntensity
317  - 2.0 * ( bottomColorIntensity * topColorIntensity );
318 }
319 
320 
321 // Special purpose blendings
322 
323 void CloudsBlending::blend( QImage * const bottom, TextureTile const * const top ) const
324 {
325  QImage const * const topImage = top->image();
326  Q_ASSERT( topImage );
327  Q_ASSERT( bottom->size() == topImage->size() );
328  int const width = bottom->width();
329  int const height = bottom->height();
330  for ( int y = 0; y < height; ++y ) {
331  for ( int x = 0; x < width; ++x ) {
332  qreal const c = qRed( topImage->pixel( x, y )) / 255.0;
333  QRgb const bottomPixel = bottom->pixel( x, y );
334  int const bottomRed = qRed( bottomPixel );
335  int const bottomGreen = qGreen( bottomPixel );
336  int const bottomBlue = qBlue( bottomPixel );
337  bottom->setPixel( x, y, qRgb(( int )( bottomRed + ( 255 - bottomRed ) * c ),
338  ( int )( bottomGreen + ( 255 - bottomGreen ) * c ),
339  ( int )( bottomBlue + ( 255 - bottomBlue ) * c )));
340  }
341  }
342 }
343 
344 
345 }
QImage::convertToFormat
QImage convertToFormat(Format format, QFlags< Qt::ImageConversionFlag > flags) const
Marble::CloudsBlending::blend
virtual void blend(QImage *const bottom, TextureTile const *const top) const
Definition: BlendingAlgorithms.cpp:323
TextureTile.h
Marble::TextureTile
A class that resembles an image tile (extends Tile).
Definition: TextureTile.h:60
QImage::setPixel
void setPixel(int x, int y, uint index_or_rgb)
Marble::GrayscaleBlending::blend
virtual void blend(QImage *const bottom, TextureTile const *const top) const
Definition: BlendingAlgorithms.cpp:41
Marble::TextureTile::image
QImage const * image() const
Returns the QImage that describes the look of the Tile.
Definition: TextureTile.h:90
BlendingAlgorithms.h
QImage::pixel
QRgb pixel(int x, int y) const
QImage::width
int width() const
QPainter
Marble::IndependentChannelBlending::blend
virtual void blend(QImage *const bottom, TextureTile const *const top) const
Definition: BlendingAlgorithms.cpp:68
abs
double abs(const Vec3 &c)
Definition: attlib.cpp:100
Marble::OverpaintBlending::blend
virtual void blend(QImage *const bottom, TextureTile const *const top) const
Definition: BlendingAlgorithms.cpp:28
QImage
QImage::size
QSize size() const
M_PI
#define M_PI
Definition: GeoDataCoordinates.h:26
QImage::height
int height() const
QImage::format
Format format() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:38 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal