8#include "EquirectScanlineTextureMapper.h"
18#include "GeoPainter.h"
19#include "MarbleDebug.h"
20#include "ScanlineTextureMapperContext.h"
21#include "StackedTileLoader.h"
22#include "TextureColorizer.h"
27class EquirectScanlineTextureMapper::RenderJob :
public QRunnable
42 const int m_tileLevel;
43 QImage *
const m_canvasImage;
46 const int m_yPaintedTop;
47 const int m_yPaintedBottom;
57 : m_tileLoader(tileLoader)
58 , m_tileLevel(tileLevel)
59 , m_canvasImage(canvasImage)
60 , m_viewport(viewport)
61 , m_mapQuality(mapQuality)
63 , m_yPaintedBottom(yBottom)
67EquirectScanlineTextureMapper::EquirectScanlineTextureMapper(
StackedTileLoader *tileLoader)
68 : TextureMapperInterface()
69 , m_tileLoader(tileLoader)
75void EquirectScanlineTextureMapper::mapTexture(
GeoPainter *painter,
78 const QRect &dirtyRect,
79 TextureColorizer *texColorizer)
81 if (m_canvasImage.
size() != viewport->size() || m_radius != viewport->radius()) {
82 const QImage::Format optimalFormat = ScanlineTextureMapperContext::optimalCanvasImageFormat(viewport);
84 if (m_canvasImage.
size() != viewport->size() || m_canvasImage.
format() != optimalFormat) {
85 m_canvasImage =
QImage(viewport->size(), optimalFormat);
88 if (!viewport->mapCoversViewport()) {
89 m_canvasImage.
fill(0);
92 m_radius = viewport->radius();
93 m_repaintNeeded =
true;
96 if (m_repaintNeeded) {
97 mapTexture(viewport, tileZoomLevel, painter->
mapQuality());
100 texColorizer->colorize(&m_canvasImage, viewport, painter->
mapQuality());
103 m_repaintNeeded =
false;
106 painter->
drawImage(dirtyRect, m_canvasImage, dirtyRect);
109void EquirectScanlineTextureMapper::mapTexture(
const ViewportParams *viewport,
int tileZoomLevel,
MapQuality mapQuality)
116 const int imageHeight = m_canvasImage.
height();
121 qreal realYTop, realYBottom, dummyX;
127 const int yTop = qBound(qreal(0.0), realYTop, qreal(imageHeight));
128 int yPaintedTop = yTop;
129 int yPaintedBottom = qBound(qreal(0.0), realYBottom, qreal(imageHeight));
131 yPaintedTop = qBound(0, yPaintedTop, imageHeight);
132 yPaintedBottom = qBound(0, yPaintedBottom, imageHeight);
135 const int yStep = (yPaintedBottom - yPaintedTop) / numThreads;
136 for (
int i = 0; i < numThreads; ++i) {
137 const int yStart = yPaintedTop + i * yStep;
138 const int yEnd = (i == numThreads - 1) ? yPaintedBottom : yPaintedTop + (i + 1) * yStep;
139 QRunnable *
const job =
new RenderJob(m_tileLoader, tileZoomLevel, &m_canvasImage, viewport, mapQuality, yStart, yEnd);
140 m_threadPool.
start(job);
144 const int clearStart = (yPaintedTop - m_oldYPaintedTop <= 0) ? yPaintedBottom : 0;
145 const int clearStop = (yPaintedTop - m_oldYPaintedTop <= 0) ? imageHeight : yTop;
147 QRgb *
const itClearBegin = (QRgb *)(m_canvasImage.
scanLine(clearStart));
148 QRgb *
const itClearEnd = (QRgb *)(m_canvasImage.
scanLine(clearStop));
150 for (QRgb *it = itClearBegin; it < itClearEnd; ++it) {
156 m_oldYPaintedTop = yPaintedTop;
161void EquirectScanlineTextureMapper::RenderJob::run()
165 const int imageHeight = m_canvasImage->
height();
166 const int imageWidth = m_canvasImage->
width();
167 const qint64 radius = m_viewport->radius();
169 const qreal rad2Pixel = (qreal)(2 * radius) / M_PI;
170 const float pixel2Rad = 1.0 / rad2Pixel;
172 const bool interlaced = (m_mapQuality ==
LowQuality);
174 const bool printQuality = (m_mapQuality ==
PrintQuality);
177 const int n = ScanlineTextureMapperContext::interpolationStep(m_viewport, m_mapQuality);
180 const qreal centerLon = m_viewport->centerLongitude();
181 const qreal centerLat = m_viewport->centerLatitude();
183 const int yCenterOffset = (int)(centerLat * rad2Pixel);
185 const int yTop = imageHeight / 2 - radius + yCenterOffset;
187 qreal leftLon = +centerLon - (imageWidth / 2 * pixel2Rad);
188 while (leftLon < -M_PI)
190 while (leftLon > M_PI)
193 const int maxInterpolationPointX = n * (int)(imageWidth / n - 1) + 1;
197 ScanlineTextureMapperContext context(m_tileLoader, m_tileLevel);
201 for (
int y = m_yPaintedTop; y < m_yPaintedBottom; ++y) {
202 QRgb *scanLine = (QRgb *)(m_canvasImage->
scanLine(y));
205 const qreal lat = M_PI / 2 - (y - yTop) * pixel2Rad;
207 for (
int x = 0; x < imageWidth; ++x) {
209 bool interpolate =
false;
210 if (x > 0 && x <= maxInterpolationPointX) {
212 lon += (n - 1) * pixel2Rad;
213 interpolate = !printQuality;
225 context.pixelValueApproxF(lon, lat, scanLine, n);
227 context.pixelValueApprox(lon, lat, scanLine, n);
232 if (x < imageWidth) {
234 context.pixelValueF(lon, lat, scanLine);
236 context.pixelValue(lon, lat, scanLine);
244 if (interlaced && y + 1 < m_yPaintedBottom) {
245 const int pixelByteSize = m_canvasImage->
bytesPerLine() / imageWidth;
247 memcpy(m_canvasImage->
scanLine(y + 1), m_canvasImage->
scanLine(y), imageWidth * pixelByteSize);
This file contains the headers for AbstractProjection.
This file contains the headers for ViewportParams.
qreal minLat() const
Returns the arbitrarily chosen minimum (southern) latitude.
qreal maxLat() const
Returns the arbitrarily chosen maximum (northern) latitude.
A 3d point representation.
A painter that allows to draw geometric primitives on the map.
MapQuality mapQuality() const
Returns the map quality.
void drawImage(const GeoDataCoordinates ¢erPosition, const QImage &image)
Draws an image at the given position. The image is placed with its center located at the given center...
Tile loading from a quad tree.
void cleanupTilehash()
Cleans up the internal tile hash.
void resetTilehash()
Resets the internal tile hash.
A public class that controls what is visible in the viewport of a Marble map.
bool screenCoordinates(const qreal lon, const qreal lat, qreal &x, qreal &y) const
Get the screen coordinates corresponding to geographical coordinates in the map.
Binds a QML item to a specific geodetic location in screen coordinates.
MapQuality
This enum is used to choose the map quality shown in the view.
@ HighQuality
High quality (e.g. antialiasing for lines)
@ PrintQuality
Print quality.
@ LowQuality
Low resolution (e.g. interlaced)
qsizetype bytesPerLine() const const
void fill(Qt::GlobalColor color)
void start(Callable &&callableToRun, int priority)
bool waitForDone(int msecs)