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