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;
238 GeoDataCoordinates yNorth(0, viewport->currentProjection()->maxLat(), 0);
239 GeoDataCoordinates ySouth(0, viewport->currentProjection()->minLat(), 0);
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.
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
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