9#include "TextureColorizer.h" 
   11#include <QElapsedTimer> 
   15#include <QSharedPointer> 
   19#include "GeoDataFeature.h" 
   20#include "GeoDataLinearRing.h" 
   21#include "GeoDataPlacemark.h" 
   22#include "GeoDataPolygon.h" 
   23#include "GeoPainter.h" 
   24#include "MarbleDebug.h" 
   25#include "MathHelper.h" 
   41    inline uchar head()
 const 
   44        return data & 0x000000FF;
 
   47    inline void enqueue(uchar value)
 
   51        data = ((data >> 8) & 0x00FFFFFF) | (value << 24);
 
   59TextureColorizer::TextureColorizer(
const QString &seafile, 
const QString &landfile)
 
   61    , m_landColor(qRgb(255, 0, 0))
 
   62    , m_seaColor(qRgb(0, 255, 0))
 
   69    gradientPainter.
begin(&gradientImage);
 
   72    int shadingStart = 120;
 
   75    shadingPainter.
begin(&shadingImage);
 
   81    filelist << seafile << landfile;
 
   83    for (
const QString &filename : std::as_const(filelist)) {
 
   92        while (!stream.atEnd()) {
 
   94            if (!evalstrg.isEmpty() && evalstrg.contains(
QLatin1Char(
'='))) {
 
  101        gradientPainter.
drawRect(0, 0, 256, 1);
 
  103        QLinearGradient shadeGradient(-shadingStart, 0, 256 - shadingStart, 0);
 
  110        const QRgb *gradientScanLine = (QRgb *)(gradientImage.scanLine(0));
 
  111        const QRgb *shadingScanLine = (QRgb *)(shadingImage.scanLine(0));
 
  113        for (
int i = 0; i < 256; ++i) {
 
  114            QRgb shadeColor = *(gradientScanLine + i);
 
  115            shadeGradient.setColorAt(0.496, shadeColor);
 
  116            shadeGradient.setColorAt(0.504, shadeColor);
 
  117            shadingPainter.
setBrush(shadeGradient);
 
  118            shadingPainter.
drawRect(0, 0, 16, 1);
 
  121            for (
int j = 0; j < 16; ++j) {
 
  122                texturepalette[j][offset + i] = *(shadingScanLine + j);
 
  128    shadingPainter.
end(); 
 
  129    gradientPainter.
end(); 
 
  131    mDebug() << 
"Time elapsed:" << t.
elapsed() << 
"ms";
 
  134void TextureColorizer::addSeaDocument(
const GeoDataDocument *seaDocument)
 
  136    m_seaDocuments.append(seaDocument);
 
  139void TextureColorizer::addLandDocument(
const GeoDataDocument *landDocument)
 
  141    m_landDocuments.append(landDocument);
 
  144void TextureColorizer::setShowRelief(
bool show)
 
  166void TextureColorizer::drawIndividualDocument(GeoPainter *painter, 
const GeoDataDocument *document)
 
  171    for (; i != 
end; ++i) {
 
  172        if (
const GeoDataPlacemark *placemark = geodata_cast<GeoDataPlacemark>(*i)) {
 
  173            if (
const auto child = geodata_cast<GeoDataLineString>(placemark->geometry())) {
 
  174                const GeoDataLinearRing ring(*child);
 
  175                painter->drawPolygon(ring);
 
  178            if (
const auto child = geodata_cast<GeoDataPolygon>(placemark->geometry())) {
 
  179                painter->drawPolygon(*child);
 
  182            if (
const auto child = geodata_cast<GeoDataLinearRing>(placemark->geometry())) {
 
  183                painter->drawPolygon(*child);
 
  189void TextureColorizer::drawTextureMap(GeoPainter *painter)
 
  191    for (
const GeoDataDocument *doc : std::as_const(m_landDocuments)) {
 
  193        painter->setBrush(
QBrush(m_landColor));
 
  194        drawIndividualDocument(painter, doc);
 
  197    for (
const GeoDataDocument *doc : std::as_const(m_seaDocuments)) {
 
  198        if (doc->isVisible()) {
 
  200            painter->setBrush(
QBrush(m_seaColor));
 
  201            drawIndividualDocument(painter, doc);
 
  206void TextureColorizer::colorize(
QImage *origimg, 
const ViewportParams *viewport, MapQuality mapQuality)
 
  208    if (m_coastImage.size() != viewport->size())
 
  212    m_coastImage.fill(
QColor(0, 0, 255, 0).rgb());
 
  216    GeoPainter painter(&m_coastImage, viewport, mapQuality);
 
  219    drawTextureMap(&painter);
 
  221    const qint64 radius = viewport->radius() * viewport->currentProjection()->clippingRadius();
 
  223    const int imgheight = origimg->
height();
 
  224    const int imgwidth = origimg->
width();
 
  225    const int imgrx = imgwidth / 2;
 
  226    const int imgry = imgheight / 2;
 
  228    const int imgradius = imgrx * imgrx + imgry * imgry;
 
  232    if (radius * radius > imgradius || !viewport->currentProjection()->isClippedToSphere()) {
 
  234        int yBottom = imgheight;
 
  236        if (!viewport->currentProjection()->isClippedToSphere() && !viewport->currentProjection()->traversablePoles()) {
 
  237            qreal realYTop, realYBottom, dummyX;
 
  240            viewport->screenCoordinates(yNorth, dummyX, realYTop);
 
  241            viewport->screenCoordinates(ySouth, dummyX, realYBottom);
 
  242            yTop = qBound(qreal(0.0), realYTop, qreal(imgheight));
 
  243            yBottom = qBound(qreal(0.0), realYBottom, qreal(imgheight));
 
  246        const int itEnd = yBottom;
 
  248        for (
int y = yTop; y < itEnd; ++y) {
 
  249            QRgb *writeData = (QRgb *)(origimg->
scanLine(y));
 
  250            const QRgb *coastData = (QRgb *)(m_coastImage.scanLine(y));
 
  252            uchar *readDataStart = origimg->
scanLine(y);
 
  253            const uchar *readDataEnd = readDataStart + imgwidth * 4;
 
  257            for (uchar *readData = readDataStart; readData < readDataEnd; readData += 4, ++writeData, ++coastData) {
 
  259                uchar &grey = *readData; 
 
  262                    emboss.enqueue(grey);
 
  263                    bump = (emboss.head() + 8 - grey);
 
  266                    } 
else if (bump > 15) {
 
  270                setPixel(coastData, writeData, bump, grey);
 
  274        int yTop = (imgry - radius < 0) ? 0 : imgry - radius;
 
  275        const int yBottom = (yTop == 0) ? imgheight : imgry + radius;
 
  279        for (
int y = yTop; y < yBottom; ++y) {
 
  280            const int dy = imgry - y;
 
  281            int rx = (int)sqrt((qreal)(radius * radius - dy * dy));
 
  283            int xRight = imgwidth;
 
  285            if (imgrx - rx > 0) {
 
  290            QRgb *writeData = (QRgb *)(origimg->
scanLine(y)) + xLeft;
 
  291            const QRgb *coastData = (QRgb *)(m_coastImage.scanLine(y)) + xLeft;
 
  293            uchar *readDataStart = origimg->
scanLine(y) + xLeft * 4;
 
  294            const uchar *readDataEnd = origimg->
scanLine(y) + xRight * 4;
 
  296            for (uchar *readData = readDataStart; readData < readDataEnd; readData += 4, ++writeData, ++coastData) {
 
  299                uchar &grey = *readData; 
 
  302                    emboss.enqueue(grey);
 
  303                    bump = (emboss.head() + 16 - grey) >> 1;
 
  306                    } 
else if (bump > 15) {
 
  310                setPixel(coastData, writeData, bump, grey);
 
  316void TextureColorizer::setPixel(
const QRgb *coastData, QRgb *writeData, 
int bump, uchar grey)
 
  318    int alpha = qRed(*coastData);
 
  320        *writeData = texturepalette[bump][grey + 0x100];
 
  321    else if (alpha == 0) {
 
  322        *writeData = texturepalette[bump][grey];
 
  324        qreal c = 1.0 / 255.0;
 
  326        QRgb landcolor = (QRgb)(texturepalette[bump][grey + 0x100]);
 
  327        QRgb watercolor = (QRgb)(texturepalette[bump][grey]);
 
  329        *writeData = qRgb((
int)(c * (alpha * qRed(landcolor) + (255 - alpha) * qRed(watercolor))),
 
  330                          (
int)(c * (alpha * qGreen(landcolor) + (255 - alpha) * qGreen(watercolor))),
 
  331                          (
int)(c * (alpha * qBlue(landcolor) + (255 - alpha) * qBlue(watercolor))));
 
This file contains the headers for AbstractProjection.
 
This file contains the headers for ViewParameters.
 
This file contains the headers for ViewportParams.
 
A 3d point representation.
 
const QList< QKeySequence > & end()
 
Binds a QML item to a specific geodetic location in screen coordinates.
 
@ HighQuality
High quality (e.g. antialiasing for lines)
 
@ PrintQuality
Print quality.
 
qint64 elapsed() const const
 
bool begin(QPaintDevice *device)
 
void drawRect(const QRect &rectangle)
 
void setBrush(Qt::BrushStyle style)
 
void setPen(Qt::PenStyle style)
 
QString left(qsizetype n) const const
 
QString mid(qsizetype position, qsizetype n) const const
 
double toDouble(bool *ok) const const