32#include <QRegularExpression>
35using namespace Qt::StringLiterals;
52 static const QSet<QString> sFilter { u
"REQUEST"_s, u
"VERSION"_s, u
"SERVICE"_s, u
"LAYERS"_s, u
"STYLES"_s, u
"SLD_VERSION"_s, u
"_DC"_s };
57 const QList<QPair<QString, QString>> queryItems = q.queryItems();
58 for (
const QPair<QString, QString> ¶m : queryItems )
60 if ( sFilter.contains( param.first.toUpper() ) )
61 q.removeAllQueryItems( param.first );
73 if ( format.compare(
"png"_L1, Qt::CaseInsensitive ) == 0 || format.compare(
"image/png"_L1, Qt::CaseInsensitive ) == 0 )
77 else if ( format.compare(
"jpg "_L1, Qt::CaseInsensitive ) == 0 || format.compare(
"image/jpeg"_L1, Qt::CaseInsensitive ) == 0 )
81 else if ( format.compare(
"webp"_L1, Qt::CaseInsensitive ) == 0 || format.compare(
"image/webp"_L1, Qt::CaseInsensitive ) == 0 )
88 const thread_local QRegularExpression modeExpr = QRegularExpression( u
"image/png\\s*;\\s*mode=([^;]+)"_s, QRegularExpression::CaseInsensitiveOption );
90 const QRegularExpressionMatch match = modeExpr.match( format );
91 const QString mode = match.captured( 1 );
92 if ( mode.compare(
"16bit"_L1, Qt::CaseInsensitive ) == 0 )
94 if ( mode.compare(
"8bit"_L1, Qt::CaseInsensitive ) == 0 )
96 if ( mode.compare(
"1bit"_L1, Qt::CaseInsensitive ) == 0 )
110 switch ( outputFormat )
114 contentType = u
"image/png"_s;
115 saveFormat = u
"PNG"_s;
119 QVector<QRgb> colorTable;
124 const QImage img256 = img.convertToFormat( QImage::Format_ARGB32 );
126 result = img256.convertToFormat( QImage::Format_Indexed8, colorTable, Qt::ColorOnly | Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection );
128 contentType = u
"image/png"_s;
129 saveFormat = u
"PNG"_s;
132 result = img.convertToFormat( QImage::Format_ARGB4444_Premultiplied );
133 contentType = u
"image/png"_s;
134 saveFormat = u
"PNG"_s;
137 result = img.convertToFormat( QImage::Format_Mono, Qt::MonoOnly | Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection );
138 contentType = u
"image/png"_s;
139 saveFormat = u
"PNG"_s;
143 contentType = u
"image/jpeg"_s;
144 saveFormat = u
"JPEG"_s;
148 contentType = u
"image/webp"_s;
149 saveFormat = u
"WEBP"_s;
153 saveFormat = u
"Unknown"_s;
158 result.setDotsPerMeterX( img.dotsPerMeterX() );
159 result.setDotsPerMeterY( img.dotsPerMeterY() );
163 response.
setHeader(
"Content-Type", contentType );
164 if ( saveFormat ==
"JPEG"_L1 || saveFormat ==
"WEBP"_L1 )
166 result.save( response.
io(), qPrintable( saveFormat ), imageQuality );
170 result.save( response.
io(), qPrintable( saveFormat ) );
176 parameter.
mValue = formatStr;
190 QHash<const QgsMapLayer *, QStringList> &acceptableLayersAndRequestNames,
192 const QStringList &requestedLayerNames,
194 QStringList requestedParentNames = QStringList(),
195 bool groupIsAnOpaqueChild =
false
200 if ( groupName.isEmpty() )
201 groupName = group->
name();
204 bool groupIsRequested = requestedLayerNames.contains( groupName );
207 if ( groupIsRequested && !groupIsAnOpaqueChild )
208 requestedParentNames << groupName;
236 else if ( name.isEmpty() )
238 name = layer->
name();
241 QStringList requestedNames = requestedParentNames;
243 if ( requestedLayerNames.contains( name ) && !isOpaqueChild )
245 requestedNames << name;
248 if ( !requestedNames.isEmpty() || requestedLayerNames.isEmpty() || projectIsRequested )
249 acceptableLayersAndRequestNames.insert( layer, requestedNames );
261 void getChildRanges(
const QgsLayerTreeGroup *layerTreeGroup,
const QMap<QString, QgsWmsLayerInfos> &wmsLayerInfos,
const QStringList &restrictedLayers, QList<QgsDateTimeRange> &dateRanges )
263 QList<QgsLayerTreeNode *> layerTreeGroupChildren = layerTreeGroup->
children();
264 for (
int i = 0; i < layerTreeGroupChildren.size(); ++i )
271 if ( !restrictedLayers.contains( treeGroupChild->
name() )
274 QList<QgsDateTimeRange> childrenDateRanges;
275 getChildRanges( treeGroupChild, wmsLayerInfos, restrictedLayers, childrenDateRanges );
276 dateRanges.append( childrenDateRanges );
284 if ( wmsLayerInfos.contains( treeLayer->
layerId() )
290 dateRanges.append( allRanges );
@ Opaque
Group can be requested, children cannot (appears like a single layer).
Layer tree group node serves as a container for layers and further groups.
QString name() const override
Returns the group's name.
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the layer tree group.
bool hasWmsTimeDimension() const
Returns whether the WMS time dimension should be computed for this group or not.
Qgis::WmsGroupRequestMode wmsGroupRequestMode() const
Returns the request mode of the group.
Layer tree node points to a map layer.
QString layerId() const
Returns the ID for the map layer associated with this node.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
Base class for nodes in a layer tree.
@ NodeGroup
Container of other groups and layers.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
NodeType nodeType() const
Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree...
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
virtual QList< QgsDateTimeRange > allTemporalRanges(QgsMapLayer *layer) const
Attempts to calculate the overall list of all temporal extents which are contained in the specified l...
Base class for all map layer types.
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
static QString wmsRootName(const QgsProject &project)
Returns the WMS root layer name defined in a QGIS project.
static bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
static QString wmsServiceUrl(const QgsProject &project, const QgsServerRequest &request=QgsServerRequest(), const QgsServerSettings &settings=QgsServerSettings())
Returns the WMS service url.
Defines requests passed to QgsService classes.
QUrl originalUrl() const
Returns the request url as seen by the web server, by default this is equal to the url seen by QGIS s...
Defines the response interface passed to QgsService.
virtual void setHeader(const QString &key, const QString &value)=0
Set a single header value replacing any existing value(s) for the same key.
virtual QIODevice * io()=0
Returns the underlying QIODevice.
Provides a way to retrieve settings by prioritizing according to environment variables,...
bool isActive() const
Returns true if the temporal property is active.
Exception thrown in case of malformed request.
WMS parameter received from the client.
Median cut implementation.
void writeImage(QgsServerResponse &response, QImage &img, const QString &formatStr, int imageQuality)
Write image response.
void collectAcceptableLayersAndRequestNames(QHash< const QgsMapLayer *, QStringList > &acceptableLayersAndRequestNames, const QgsProject &project, const QStringList &requestedLayerNames)
Collects the acceptableLayersAndRequestNames, a hash of all the layers that can be rendered and for e...
void medianCut(QVector< QRgb > &colorTable, int nColors, const QImage &inputImage)
Median cut implementation used when reducing RGB colors to palletized colors.
QString implementationVersion()
Returns the highest version supported by this implementation.
void _collectAcceptableLayersAndRequestNames(QHash< const QgsMapLayer *, QStringList > &acceptableLayersAndRequestNames, const QgsProject &project, const QStringList &requestedLayerNames, const QgsLayerTreeGroup *group, QStringList requestedParentNames=QStringList(), bool groupIsAnOpaqueChild=false)
Collects the acceptableLayersAndRequestNames recursively, a hash of all the layers that can be render...
void getChildRanges(const QgsLayerTreeGroup *layerTreeGroup, const QMap< QString, QgsWmsLayerInfos > &wmsLayerInfos, const QStringList &restrictedLayers, QList< QgsDateTimeRange > &dateRanges)
Update recursively dateRanges with all layerTreeGroup children date ranges.
ImageOutputFormat
Supported image output format.
@ Unknown
Unknown/invalid format.
ImageOutputFormat parseImageFormat(const QString &format)
Parse image format parameter.
QUrl serviceUrl(const QgsServerRequest &request, const QgsProject *project, const QgsServerSettings &settings)
Returns WMS service URL.