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

marble

  • sources
  • kde-4.12
  • kdeedu
  • marble
  • src
  • lib
  • marble
TextureColorizer.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2006-2007 Torsten Rahn <tackat@kde.org>
9 // Copyright 2007 Inge Wallin <ingwa@kde.org>
10 // Copyright 2008 Carlos Licea <carlos.licea@kdemail.net>
11 // Copyright 2012 Cezar Mocan <mocancezar@gmail.com>
12 //
13 
14 #include "TextureColorizer.h"
15 
16 #include <qmath.h>
17 #include <QFile>
18 #include <QSharedPointer>
19 #include <QString>
20 #include <QVector>
21 #include <QTime>
22 #include <QColor>
23 #include <QImage>
24 #include <QPainter>
25 
26 #include "MarbleGlobal.h"
27 #include "GeoPainter.h"
28 #include "MarbleDebug.h"
29 #include "VectorComposer.h"
30 #include "ViewParams.h"
31 #include "ViewportParams.h"
32 #include "MathHelper.h"
33 #include "GeoDataFeature.h"
34 #include "GeoDataTypes.h"
35 #include "GeoDataPlacemark.h"
36 #include "GeoDataDocument.h"
37 
38 namespace Marble
39 {
40 
41 class EmbossFifo
42 {
43 public:
44  EmbossFifo()
45  : x1( 0 )
46  , x2( 0 )
47  , x3( 0 )
48  , x4( 0 )
49  {}
50 
51  inline uchar head() const { return x1; }
52 
53  inline EmbossFifo &operator<<( uchar value )
54  {
55  x1 = x2;
56  x2 = x3;
57  x3 = x4;
58  x4 = value;
59 
60  return *this;
61  }
62 
63 private:
64  uchar x1;
65  uchar x2;
66  uchar x3;
67  uchar x4;
68 };
69 
70 
71 TextureColorizer::TextureColorizer( const QString &seafile,
72  const QString &landfile,
73  VectorComposer *veccomposer )
74  : m_veccomposer( veccomposer ),
75  m_landColor(qRgb( 255, 0, 0 ) ),
76  m_seaColor( qRgb( 0, 255, 0 ) )
77 {
78  QTime t;
79  t.start();
80 
81  QImage gradientImage ( 256, 1, QImage::Format_RGB32 );
82  QPainter gradientPainter;
83  gradientPainter.begin( &gradientImage );
84  gradientPainter.setPen( Qt::NoPen );
85 
86 
87  int shadingStart = 120;
88  QImage shadingImage ( 16, 1, QImage::Format_RGB32 );
89  QPainter shadingPainter;
90  shadingPainter.begin( &shadingImage );
91  shadingPainter.setPen( Qt::NoPen );
92 
93  int offset = 0;
94 
95  QStringList filelist;
96  filelist << seafile << landfile;
97 
98  foreach ( const QString &filename, filelist ) {
99 
100  QLinearGradient gradient( 0, 0, 256, 0 );
101 
102  QFile file( filename );
103  file.open( QIODevice::ReadOnly );
104  QTextStream stream( &file ); // read the data from the file
105 
106  QString evalstrg;
107 
108  while ( !stream.atEnd() ) {
109  stream >> evalstrg;
110  if ( !evalstrg.isEmpty() && evalstrg.contains( '=' ) ) {
111  QString colorValue = evalstrg.left( evalstrg.indexOf( '=' ) );
112  QString colorPosition = evalstrg.mid( evalstrg.indexOf( '=' ) + 1 );
113  gradient.setColorAt( colorPosition.toDouble(),
114  QColor( colorValue ) );
115  }
116  }
117  gradientPainter.setBrush( gradient );
118  gradientPainter.drawRect( 0, 0, 256, 1 );
119 
120  QLinearGradient shadeGradient( - shadingStart, 0, 256 - shadingStart, 0 );
121 
122  shadeGradient.setColorAt(0.00, QColor(Qt::white));
123  shadeGradient.setColorAt(0.15, QColor(Qt::white));
124  shadeGradient.setColorAt(0.75, QColor(Qt::black));
125  shadeGradient.setColorAt(1.00, QColor(Qt::black));
126 
127  const QRgb * gradientScanLine = (QRgb*)( gradientImage.scanLine( 0 ) );
128  const QRgb * shadingScanLine = (QRgb*)( shadingImage.scanLine( 0 ) );
129 
130  for ( int i = 0; i < 256; ++i ) {
131 
132  QRgb shadeColor = *(gradientScanLine + i );
133  shadeGradient.setColorAt(0.496, shadeColor);
134  shadeGradient.setColorAt(0.504, shadeColor);
135  shadingPainter.setBrush( shadeGradient );
136  shadingPainter.drawRect( 0, 0, 16, 1 );
137 
138  // populate texturepalette[][]
139  for ( int j = 0; j < 16; ++j ) {
140  texturepalette[j][offset + i] = *(shadingScanLine + j );
141  }
142  }
143 
144  offset += 256;
145  }
146  shadingPainter.end(); // Need to explicitly tell painter lifetime to avoid crash
147  gradientPainter.end(); // on some systems.
148 
149  mDebug() << Q_FUNC_INFO << "Time elapsed:" << t.elapsed() << "ms";
150 }
151 
152 void TextureColorizer::addSeaDocument( const GeoDataDocument *seaDocument )
153 {
154  m_seaDocuments.append( seaDocument );
155 }
156 
157 void TextureColorizer::addLandDocument( const GeoDataDocument *landDocument )
158 {
159  m_landDocuments.append( landDocument );
160 }
161 
162 void TextureColorizer::setShowRelief( bool show )
163 {
164  m_showRelief = show;
165 }
166 
167 // This function takes two images, both in viewParams:
168 // - The coast image, which has a number of colors where each color
169 // represents a sort of terrain (ex: land/sea)
170 // - The canvas image, which has a gray scale image, often
171 // representing a height field.
172 //
173 // It then uses the values of the pixels in the coast image to select
174 // a color map. The value of the pixel in the canvas image is used as
175 // an index into the selected color map and the resulting color is
176 // written back to the canvas image. This way we can have different
177 // color schemes for land and water.
178 //
179 // In addition to this, a simple form of bump mapping is performed to
180 // increase the illusion of height differences (see the variable
181 // showRelief).
182 //
183 
184 void TextureColorizer::drawIndividualDocument( GeoPainter *painter, const GeoDataDocument *document )
185 {
186  QVector<GeoDataFeature*>::ConstIterator i = document->constBegin();
187  QVector<GeoDataFeature*>::ConstIterator end = document->constEnd();
188 
189  for ( ; i != end; ++i ) {
190  if ( (*i)->nodeType() == GeoDataTypes::GeoDataPlacemarkType ) {
191 
192  const GeoDataPlacemark *placemark = static_cast<const GeoDataPlacemark*>( *i );
193 
194  if ( placemark->geometry()->nodeType() == GeoDataTypes::GeoDataLineStringType ) {
195  const GeoDataLineString *child = static_cast<const GeoDataLineString*>( placemark->geometry() );
196  const GeoDataLinearRing ring( *child );
197  painter->drawPolygon( ring );
198  }
199 
200  if ( placemark->geometry()->nodeType() == GeoDataTypes::GeoDataPolygonType ) {
201  const GeoDataPolygon *child = static_cast<const GeoDataPolygon*>( placemark->geometry() );
202  painter->drawPolygon( *child );
203  }
204 
205  if ( placemark->geometry()->nodeType() == GeoDataTypes::GeoDataLinearRingType ) {
206  const GeoDataLinearRing *child = static_cast<const GeoDataLinearRing*>( placemark->geometry() );
207  painter->drawPolygon( *child );
208  }
209  }
210  }
211 }
212 
213 void TextureColorizer::drawTextureMap( GeoPainter *painter )
214 {
215  foreach( const GeoDataDocument *doc, m_landDocuments ) {
216  painter->setPen( QPen( Qt::NoPen ) );
217  painter->setBrush( QBrush( m_landColor ) );
218  drawIndividualDocument( painter, doc );
219  }
220 
221  foreach( const GeoDataDocument *doc, m_seaDocuments ) {
222  if ( doc->isVisible() ) {
223  painter->setPen( Qt::NoPen );
224  painter->setBrush( QBrush( m_seaColor ) );
225  drawIndividualDocument( painter, doc );
226  }
227  }
228 }
229 
230 void TextureColorizer::colorize( QImage *origimg, const ViewportParams *viewport, MapQuality mapQuality )
231 {
232  if ( m_coastImage.size() != viewport->size() )
233  m_coastImage = QImage( viewport->size(), QImage::Format_RGB32 );
234 
235  // update coast image
236  m_coastImage.fill( QColor( 0, 0, 255, 0).rgb() );
237 
238  const bool antialiased = mapQuality == HighQuality
239  || mapQuality == PrintQuality;
240 
241  GeoPainter painter( &m_coastImage, viewport, mapQuality );
242  painter.setRenderHint( QPainter::Antialiasing, antialiased );
243 
244  if ( m_landDocuments.isEmpty() ) {
245  m_veccomposer->drawTextureMap( &painter, viewport );
246  } else {
247  drawTextureMap( &painter );
248  }
249 
250  const qint64 radius = viewport->radius();
251 
252  const int imgheight = origimg->height();
253  const int imgwidth = origimg->width();
254  const int imgrx = imgwidth / 2;
255  const int imgry = imgheight / 2;
256  // This variable is not used anywhere..
257  const int imgradius = imgrx * imgrx + imgry * imgry;
258 
259  int bump = 8;
260 
261  if ( radius * radius > imgradius
262  || viewport->projection() == Equirectangular
263  || viewport->projection() == Mercator )
264  {
265  int yTop = 0;
266  int yBottom = imgheight;
267 
268  if( viewport->projection() == Equirectangular
269  || viewport->projection() == Mercator )
270  {
271  // Calculate translation of center point
272  const qreal centerLat = viewport->centerLatitude();
273 
274  const float rad2Pixel = (qreal)( 2 * radius ) / M_PI;
275  if ( viewport->projection() == Equirectangular ) {
276  int yCenterOffset = (int)( centerLat * rad2Pixel );
277  yTop = ( imgry - radius + yCenterOffset < 0)? 0 : imgry - radius + yCenterOffset;
278  yBottom = ( imgry + yCenterOffset + radius > imgheight )? imgheight : imgry + yCenterOffset + radius;
279  }
280  else if ( viewport->projection() == Mercator ) {
281  int yCenterOffset = (int)( asinh( tan( centerLat ) ) * rad2Pixel );
282  yTop = ( imgry - 2 * radius + yCenterOffset < 0 ) ? 0 : imgry - 2 * radius + yCenterOffset;
283  yBottom = ( imgry + 2 * radius + yCenterOffset > imgheight )? imgheight : imgry + 2 * radius + yCenterOffset;
284  }
285  }
286 
287  const int itEnd = yBottom;
288 
289  for (int y = yTop; y < itEnd; ++y) {
290 
291  QRgb *writeData = (QRgb*)( origimg->scanLine( y ) );
292  const QRgb *coastData = (QRgb*)( m_coastImage.scanLine( y ) );
293 
294  uchar *readDataStart = origimg->scanLine( y );
295  const uchar *readDataEnd = readDataStart + imgwidth*4;
296 
297  EmbossFifo emboss;
298 
299  for ( uchar* readData = readDataStart;
300  readData < readDataEnd;
301  readData += 4, ++writeData, ++coastData )
302  {
303 
304  // Cheap Emboss / Bumpmapping
305  uchar& grey = *readData; // qBlue(*data);
306 
307  if ( m_showRelief ) {
308  emboss << grey;
309  bump = ( emboss.head() + 8 - grey );
310  if ( bump < 0 ) bump = 0;
311  if ( bump > 15 ) bump = 15;
312  }
313  setPixel( coastData, writeData, bump, grey );
314  }
315  }
316  }
317  else {
318  int yTop = ( imgry-radius < 0 ) ? 0 : imgry-radius;
319  const int yBottom = ( yTop == 0 ) ? imgheight : imgry + radius;
320 
321  EmbossFifo emboss;
322 
323  for ( int y = yTop; y < yBottom; ++y ) {
324  const int dy = imgry - y;
325  int rx = (int)sqrt( (qreal)( radius * radius - dy * dy ) );
326  int xLeft = 0;
327  int xRight = imgwidth;
328 
329  if ( imgrx-rx > 0 ) {
330  xLeft = imgrx - rx;
331  xRight = imgrx + rx;
332  }
333 
334  QRgb *writeData = (QRgb*)( origimg->scanLine( y ) ) + xLeft;
335  const QRgb *coastData = (QRgb*)( m_coastImage.scanLine( y ) ) + xLeft;
336 
337  uchar *readDataStart = origimg->scanLine( y ) + xLeft * 4;
338  const uchar *readDataEnd = origimg->scanLine( y ) + xRight * 4;
339 
340 
341  for ( uchar* readData = readDataStart;
342  readData < readDataEnd;
343  readData += 4, ++writeData, ++coastData )
344  {
345  // Cheap Emboss / Bumpmapping
346 
347  uchar& grey = *readData; // qBlue(*data);
348 
349  if ( m_showRelief ) {
350  emboss << grey;
351  bump = ( emboss.head() + 16 - grey ) >> 1;
352  if ( bump > 15 ) bump = 15;
353  if ( bump < 0 ) bump = 0;
354  }
355  setPixel( coastData, writeData, bump, grey );
356  }
357  }
358  }
359 }
360 
361 void TextureColorizer::setPixel( const QRgb *coastData, QRgb *writeData, int bump, uchar grey )
362 {
363  int alpha = qRed( *coastData );
364  if ( alpha == 255 )
365  *writeData = texturepalette[bump][grey + 0x100];
366  else if( alpha == 0 ){
367  *writeData = texturepalette[bump][grey];
368  }
369  else {
370  qreal c = 1.0 / 255.0;
371 
372  QRgb landcolor = (QRgb)(texturepalette[bump][grey + 0x100]);
373  QRgb watercolor = (QRgb)(texturepalette[bump][grey]);
374 
375  *writeData = qRgb(
376  (int) ( c * ( alpha * qRed( landcolor )
377  + ( 255 - alpha ) * qRed( watercolor ) ) ),
378  (int) ( c * ( alpha * qGreen( landcolor )
379  + ( 255 - alpha ) * qGreen( watercolor ) ) ),
380  (int) ( c * ( alpha * qBlue( landcolor )
381  + ( 255 - alpha ) * qBlue( watercolor ) ) )
382  );
383  }
384 }
385 }
QPainter
GeoDataDocument.h
Marble::TextureColorizer::drawIndividualDocument
void drawIndividualDocument(GeoPainter *painter, const GeoDataDocument *document)
Definition: TextureColorizer.cpp:184
Marble::GeoDataGeometry::nodeType
virtual const char * nodeType() const
Provides type information for downcasting a GeoData.
Definition: GeoDataGeometry.cpp:77
Marble::GeoDataTypes::GeoDataLinearRingType
const char * GeoDataLinearRingType
Definition: GeoDataTypes.cpp:48
Marble::GeoDataDocument
A container for Features, Styles and in the future Schemas.
Definition: GeoDataDocument.h:64
Marble::GeoPainter::drawPolygon
void drawPolygon(const GeoDataLinearRing &linearRing, Qt::FillRule fillRule=Qt::OddEvenFill)
Draws a given linear ring (a "polygon without holes").
Definition: GeoPainter.cpp:560
Marble::ViewportParams::size
QSize size() const
Definition: ViewportParams.cpp:260
Marble::GeoDataLinearRing
A LinearRing that allows to store a closed, contiguous set of line segments.
Definition: GeoDataLinearRing.h:68
Marble::GeoDataTypes::GeoDataPolygonType
const char * GeoDataPolygonType
Definition: GeoDataTypes.cpp:65
Marble::GeoPainter
A painter that allows to draw geometric primitives on the map.
Definition: GeoPainter.h:98
Marble::GeoDataContainer::constBegin
QVector< GeoDataFeature * >::ConstIterator constBegin() const
Definition: GeoDataContainer.cpp:234
Marble::TextureColorizer::setShowRelief
void setShowRelief(bool show)
Definition: TextureColorizer.cpp:162
Marble::TextureColorizer::colorize
void colorize(QImage *origimg, const ViewportParams *viewport, MapQuality mapQuality)
Definition: TextureColorizer.cpp:230
Marble::GeoDataTypes::GeoDataPlacemarkType
const char * GeoDataPlacemarkType
Definition: GeoDataTypes.cpp:62
Marble::GeoDataFeature::isVisible
bool isVisible() const
Return whether this feature is visible or not.
Definition: GeoDataFeature.cpp:581
Marble::TextureColorizer::addLandDocument
void addLandDocument(const GeoDataDocument *landDocument)
Definition: TextureColorizer.cpp:157
Marble::PrintQuality
Print quality.
Definition: MarbleGlobal.h:85
Marble::ViewportParams::projection
Projection projection() const
Definition: ViewportParams.cpp:129
Marble::MapQuality
MapQuality
This enum is used to choose the map quality shown in the view.
Definition: MarbleGlobal.h:80
Marble::TextureColorizer::addSeaDocument
void addSeaDocument(const GeoDataDocument *seaDocument)
Definition: TextureColorizer.cpp:152
Marble::VectorComposer::drawTextureMap
void drawTextureMap(GeoPainter *painter, const ViewportParams *viewport)
Definition: VectorComposer.cpp:187
Marble::GeoDataPlacemark::geometry
GeoDataGeometry * geometry() const
The geometry of the GeoDataPlacemark is to be rendered to the marble map along with the icon at the c...
Definition: GeoDataPlacemark.cpp:63
MarbleDebug.h
TextureColorizer.h
ViewParams.h
This file contains the headers for ViewParameters.
Marble::Equirectangular
Flat projection ("plate carree")
Definition: MarbleGlobal.h:46
VectorComposer.h
GeoDataFeature.h
Marble::Mercator
Mercator projection.
Definition: MarbleGlobal.h:47
Marble::GeoDataContainer::constEnd
QVector< GeoDataFeature * >::ConstIterator constEnd() const
Definition: GeoDataContainer.cpp:239
asinh
double asinh(double xval)
Definition: sgp4ext.cpp:211
MathHelper.h
Marble::GeoDataPolygon
A polygon that can have "holes".
Definition: GeoDataPolygon.h:81
Marble::GeoDataTypes::GeoDataLineStringType
const char * GeoDataLineStringType
Definition: GeoDataTypes.cpp:49
Marble::VectorComposer
Definition: VectorComposer.h:40
GeoPainter.h
MarbleGlobal.h
GeoDataPlacemark.h
Marble::GeoDataLineString
A LineString that allows to store a contiguous set of line segments.
Definition: GeoDataLineString.h:75
Marble::TextureColorizer::drawTextureMap
void drawTextureMap(GeoPainter *painter)
Definition: TextureColorizer.cpp:213
Marble::ViewportParams
A public class that controls what is visible in the viewport of a Marble map.
Definition: ViewportParams.h:44
ViewportParams.h
This file contains the headers for ViewportParams.
Marble::ViewportParams::centerLatitude
qreal centerLatitude() const
Definition: ViewportParams.cpp:294
Marble::ViewportParams::radius
int radius() const
Definition: ViewportParams.cpp:195
Marble::HighQuality
High quality (e.g. antialiasing for lines)
Definition: MarbleGlobal.h:84
Marble::TextureColorizer::TextureColorizer
TextureColorizer(const QString &seafile, const QString &landfile, VectorComposer *veccomposer)
Definition: TextureColorizer.cpp:71
M_PI
#define M_PI
Definition: GeoDataCoordinates.h:26
Marble::operator<<
QTextStream & operator<<(QTextStream &stream, const RoutingInstruction &i)
Definition: RoutingInstruction.cpp:455
GeoDataTypes.h
Marble::GeoDataPlacemark
a class representing a point of interest on the map
Definition: GeoDataPlacemark.h:54
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
Marble::TextureColorizer::setPixel
void setPixel(const QRgb *coastData, QRgb *writeData, int bump, uchar grey)
Definition: TextureColorizer.cpp:361
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:38:53 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
  • kstars
  • libkdeedu
  •   keduvocdocument
  • 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