9 #include "TextureColorizer.h"
13 #include <QSharedPointer>
15 #include <QElapsedTimer>
18 #include "GeoPainter.h"
19 #include "MarbleDebug.h"
22 #include "MathHelper.h"
23 #include "GeoDataLinearRing.h"
24 #include "GeoDataPolygon.h"
25 #include "GeoDataFeature.h"
26 #include "GeoDataPlacemark.h"
40 inline uchar head()
const
43 return data & 0x000000FF;
46 inline void enqueue(uchar value)
50 data = ((data >> 8) & 0x00FFFFFF) | (value << 24);
59 TextureColorizer::TextureColorizer(
const QString &seafile,
61 : m_showRelief( false ),
62 m_landColor(qRgb( 255, 0, 0 ) ),
63 m_seaColor( qRgb( 0, 255, 0 ) )
70 gradientPainter.
begin( &gradientImage );
74 int shadingStart = 120;
77 shadingPainter.
begin( &shadingImage );
83 filelist << seafile << landfile;
85 for (
const QString &filename: filelist ) {
89 QFile file( filename );
95 while ( !stream.atEnd() ) {
97 if (!evalstrg.isEmpty() && evalstrg.contains(
QLatin1Char(
'='))) {
100 gradient.setColorAt( colorPosition.
toDouble(),
104 gradientPainter.
setBrush( gradient );
105 gradientPainter.
drawRect( 0, 0, 256, 1 );
107 QLinearGradient shadeGradient( - shadingStart, 0, 256 - shadingStart, 0 );
114 const QRgb * gradientScanLine = (QRgb*)( gradientImage.scanLine( 0 ) );
115 const QRgb * shadingScanLine = (QRgb*)( shadingImage.scanLine( 0 ) );
117 for (
int i = 0; i < 256; ++i ) {
119 QRgb shadeColor = *(gradientScanLine + i );
120 shadeGradient.setColorAt(0.496, shadeColor);
121 shadeGradient.setColorAt(0.504, shadeColor);
122 shadingPainter.
setBrush( shadeGradient );
123 shadingPainter.
drawRect( 0, 0, 16, 1 );
126 for (
int j = 0; j < 16; ++j ) {
127 texturepalette[j][offset + i] = *(shadingScanLine + j );
133 shadingPainter.
end();
134 gradientPainter.
end();
136 mDebug() <<
"Time elapsed:" << t.
elapsed() <<
"ms";
139 void TextureColorizer::addSeaDocument(
const GeoDataDocument *seaDocument )
141 m_seaDocuments.append( seaDocument );
144 void TextureColorizer::addLandDocument(
const GeoDataDocument *landDocument )
146 m_landDocuments.append( landDocument );
149 void TextureColorizer::setShowRelief(
bool show )
171 void TextureColorizer::drawIndividualDocument( GeoPainter *painter,
const GeoDataDocument *document )
176 for ( ; i !=
end; ++i ) {
177 if (
const GeoDataPlacemark *placemark = geodata_cast<GeoDataPlacemark>(*i)) {
178 if (
const GeoDataLineString *child = geodata_cast<GeoDataLineString>(placemark->geometry())) {
179 const GeoDataLinearRing ring( *child );
180 painter->drawPolygon( ring );
183 if (
const GeoDataPolygon *child = geodata_cast<GeoDataPolygon>(placemark->geometry())) {
184 painter->drawPolygon( *child );
187 if (
const GeoDataLinearRing *child = geodata_cast<GeoDataLinearRing>(placemark->geometry())) {
188 painter->drawPolygon( *child );
194 void TextureColorizer::drawTextureMap( GeoPainter *painter )
196 for(
const GeoDataDocument *doc: m_landDocuments ) {
198 painter->setBrush(
QBrush( m_landColor ) );
199 drawIndividualDocument( painter, doc );
202 for(
const GeoDataDocument *doc: m_seaDocuments ) {
203 if ( doc->isVisible() ) {
205 painter->setBrush(
QBrush( m_seaColor ) );
206 drawIndividualDocument( painter, doc );
211 void TextureColorizer::colorize(
QImage *origimg,
const ViewportParams *viewport,
MapQuality mapQuality )
213 if ( m_coastImage.size() != viewport->size() )
217 m_coastImage.fill(
QColor( 0, 0, 255, 0).rgb() );
222 GeoPainter painter( &m_coastImage, viewport, mapQuality );
225 drawTextureMap( &painter );
227 const qint64 radius = viewport->radius() * viewport->currentProjection()->clippingRadius();
229 const int imgheight = origimg->
height();
230 const int imgwidth = origimg->
width();
231 const int imgrx = imgwidth / 2;
232 const int imgry = imgheight / 2;
234 const int imgradius = imgrx * imgrx + imgry * imgry;
238 if ( radius * radius > imgradius
239 || !viewport->currentProjection()->isClippedToSphere() )
242 int yBottom = imgheight;
244 if( !viewport->currentProjection()->isClippedToSphere() && !viewport->currentProjection()->traversablePoles() )
246 qreal realYTop, realYBottom, dummyX;
247 GeoDataCoordinates yNorth(0, viewport->currentProjection()->maxLat(), 0);
248 GeoDataCoordinates ySouth(0, viewport->currentProjection()->minLat(), 0);
249 viewport->screenCoordinates(yNorth, dummyX, realYTop );
250 viewport->screenCoordinates(ySouth, dummyX, realYBottom );
251 yTop = qBound(qreal(0.0), realYTop, qreal(imgheight));
252 yBottom = qBound(qreal(0.0), realYBottom, qreal(imgheight));
255 const int itEnd = yBottom;
257 for (
int y = yTop; y < itEnd; ++y) {
259 QRgb *writeData = (QRgb*)( origimg->
scanLine( y ) );
260 const QRgb *coastData = (QRgb*)( m_coastImage.scanLine( y ) );
262 uchar *readDataStart = origimg->
scanLine( y );
263 const uchar *readDataEnd = readDataStart + imgwidth*4;
267 for ( uchar* readData = readDataStart;
268 readData < readDataEnd;
269 readData += 4, ++writeData, ++coastData )
273 uchar& grey = *readData;
275 if ( m_showRelief ) {
276 emboss.enqueue(grey);
277 bump = ( emboss.head() + 8 - grey );
280 }
else if (bump > 15) {
284 setPixel( coastData, writeData, bump, grey );
289 int yTop = ( imgry-radius < 0 ) ? 0 : imgry-radius;
290 const int yBottom = ( yTop == 0 ) ? imgheight : imgry + radius;
294 for (
int y = yTop; y < yBottom; ++y ) {
295 const int dy = imgry - y;
296 int rx = (int)sqrt( (qreal)( radius * radius - dy * dy ) );
298 int xRight = imgwidth;
300 if ( imgrx-rx > 0 ) {
305 QRgb *writeData = (QRgb*)( origimg->
scanLine( y ) ) + xLeft;
306 const QRgb *coastData = (QRgb*)( m_coastImage.scanLine( y ) ) + xLeft;
308 uchar *readDataStart = origimg->
scanLine( y ) + xLeft * 4;
309 const uchar *readDataEnd = origimg->
scanLine( y ) + xRight * 4;
312 for ( uchar* readData = readDataStart;
313 readData < readDataEnd;
314 readData += 4, ++writeData, ++coastData )
318 uchar& grey = *readData;
320 if ( m_showRelief ) {
321 emboss.enqueue(grey);
322 bump = ( emboss.head() + 16 - grey ) >> 1;
325 }
else if (bump > 15) {
329 setPixel( coastData, writeData, bump, grey );
335 void TextureColorizer::setPixel(
const QRgb *coastData, QRgb *writeData,
int bump, uchar grey )
337 int alpha = qRed( *coastData );
339 *writeData = texturepalette[bump][grey + 0x100];
340 else if( alpha == 0 ){
341 *writeData = texturepalette[bump][grey];
344 qreal c = 1.0 / 255.0;
346 QRgb landcolor = (QRgb)(texturepalette[bump][grey + 0x100]);
347 QRgb watercolor = (QRgb)(texturepalette[bump][grey]);
350 (
int) ( c * ( alpha * qRed( landcolor )
351 + ( 255 - alpha ) * qRed( watercolor ) ) ),
352 (
int) ( c * ( alpha * qGreen( landcolor )
353 + ( 255 - alpha ) * qGreen( watercolor ) ) ),
354 (
int) ( c * ( alpha * qBlue( landcolor )
355 + ( 255 - alpha ) * qBlue( watercolor ) ) )