diff --git a/src/server/qgsrequesthandler.cpp b/src/server/qgsrequesthandler.cpp index 5e578e3f07a..c0d7ef9e399 100644 --- a/src/server/qgsrequesthandler.cpp +++ b/src/server/qgsrequesthandler.cpp @@ -103,7 +103,6 @@ bool QgsRequestHandler::headersSent() const return mResponse.headersSent(); } - void QgsRequestHandler::appendBody( const QByteArray &body ) { mResponse.write( body ); @@ -152,62 +151,6 @@ QString QgsRequestHandler::formatToMimeType( const QString& format ) const return format; } -void QgsRequestHandler::setGetMapResponse( const QString& service, QImage* img, int imageQuality = -1 ) -{ - Q_UNUSED( service ); - QgsMessageLog::logMessage( QStringLiteral( "setting getmap response..." ) ); - if ( img ) - { - bool png16Bit = ( mFormatString.compare( QLatin1String( "image/png; mode=16bit" ), Qt::CaseInsensitive ) == 0 ); - bool png8Bit = ( mFormatString.compare( QLatin1String( "image/png; mode=8bit" ), Qt::CaseInsensitive ) == 0 ); - bool png1Bit = ( mFormatString.compare( QLatin1String( "image/png; mode=1bit" ), Qt::CaseInsensitive ) == 0 ); - if ( mFormat != QLatin1String( "PNG" ) && mFormat != QLatin1String( "JPG" ) && !png16Bit && !png8Bit && !png1Bit ) - { - QgsMessageLog::logMessage( QStringLiteral( "service exception - incorrect image format requested..." ) ); - setServiceException( QgsMapServiceException( QStringLiteral( "InvalidFormat" ), "Output format '" + mFormatString + "' is not supported in the GetMap request" ) ); - return; - } - - //store the image in a QByteArray and set it directly - QByteArray ba; - QBuffer buffer( &ba ); - buffer.open( QIODevice::WriteOnly ); - - // Do not use imageQuality for PNG images - // For now, QImage expects quality to be a range 0-9 for PNG - if ( mFormat == QLatin1String( "PNG" ) ) - { - imageQuality = -1; - } - - if ( png8Bit ) - { - QVector colorTable; - medianCut( colorTable, 256, *img ); - QImage palettedImg = img->convertToFormat( QImage::Format_Indexed8, colorTable, Qt::ColorOnly | Qt::ThresholdDither | - Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection ); - palettedImg.save( &buffer, "PNG", imageQuality ); - } - else if ( png16Bit ) - { - QImage palettedImg = img->convertToFormat( QImage::Format_ARGB4444_Premultiplied ); - palettedImg.save( &buffer, "PNG", imageQuality ); - } - else if ( png1Bit ) - { - QImage palettedImg = img->convertToFormat( QImage::Format_Mono, Qt::MonoOnly | Qt::ThresholdDither | - Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection ); - palettedImg.save( &buffer, "PNG", imageQuality ); - } - else - { - img->save( &buffer, mFormat.toUtf8().data(), imageQuality ); - } - - setHttpResponse( ba, formatToMimeType( mFormat ) ); - } -} - void QgsRequestHandler::setGetCapabilitiesResponse( const QDomDocument& doc ) { QByteArray ba = doc.toByteArray(); @@ -226,134 +169,6 @@ void QgsRequestHandler::setXmlResponse( const QDomDocument& doc, const QString& setHttpResponse( ba, mimeType ); } -void QgsRequestHandler::setGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ) -{ - QByteArray ba; - QgsMessageLog::logMessage( "Info format is:" + infoFormat ); - - if ( infoFormat == QLatin1String( "text/xml" ) || infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) ) - { - ba = infoDoc.toByteArray(); - } - else if ( infoFormat == QLatin1String( "text/plain" ) || infoFormat == QLatin1String( "text/html" ) ) - { - //create string - QString featureInfoString; - - if ( infoFormat == QLatin1String( "text/plain" ) ) - { - featureInfoString.append( "GetFeatureInfo results\n" ); - featureInfoString.append( "\n" ); - } - else if ( infoFormat == QLatin1String( "text/html" ) ) - { - featureInfoString.append( "\n" ); - featureInfoString.append( " GetFeatureInfo results \n" ); - featureInfoString.append( "\n" ); - featureInfoString.append( "\n" ); - featureInfoString.append( "\n" ); - } - - QDomNodeList layerList = infoDoc.elementsByTagName( QStringLiteral( "Layer" ) ); - - //layer loop - for ( int i = 0; i < layerList.size(); ++i ) - { - QDomElement layerElem = layerList.at( i ).toElement(); - if ( infoFormat == QLatin1String( "text/plain" ) ) - { - featureInfoString.append( "Layer '" + layerElem.attribute( QStringLiteral( "name" ) ) + "'\n" ); - } - else if ( infoFormat == QLatin1String( "text/html" ) ) - { - featureInfoString.append( "\n" ); - featureInfoString.append( "\n" ); - featureInfoString.append( "
" ); - } - - //feature loop (for vector layers) - QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral( "Feature" ) ); - QDomElement currentFeatureElement; - - if ( featureNodeList.size() < 1 ) //raster layer? - { - QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral( "Attribute" ) ); - for ( int j = 0; j < attributeNodeList.size(); ++j ) - { - QDomElement attributeElement = attributeNodeList.at( j ).toElement(); - if ( infoFormat == QLatin1String( "text/plain" ) ) - { - featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" + - attributeElement.attribute( QStringLiteral( "value" ) ) + "'\n" ); - } - else if ( infoFormat == QLatin1String( "text/html" ) ) - { - featureInfoString.append( "\n" ); - } - } - } - else //vector layer - { - for ( int j = 0; j < featureNodeList.size(); ++j ) - { - QDomElement featureElement = featureNodeList.at( j ).toElement(); - if ( infoFormat == QLatin1String( "text/plain" ) ) - { - featureInfoString.append( "Feature " + featureElement.attribute( QStringLiteral( "id" ) ) + "\n" ); - } - else if ( infoFormat == QLatin1String( "text/html" ) ) - { - featureInfoString.append( "
Layer" + layerElem.attribute( QStringLiteral( "name" ) ) + "
" + attributeElement.attribute( QStringLiteral( "name" ) ) + "" + - attributeElement.attribute( QStringLiteral( "value" ) ) + "
\n" ); - featureInfoString.append( "\n" ); - } - //attribute loop - QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral( "Attribute" ) ); - for ( int k = 0; k < attributeNodeList.size(); ++k ) - { - QDomElement attributeElement = attributeNodeList.at( k ).toElement(); - if ( infoFormat == QLatin1String( "text/plain" ) ) - { - featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" + - attributeElement.attribute( QStringLiteral( "value" ) ) + "'\n" ); - } - else if ( infoFormat == QLatin1String( "text/html" ) ) - { - featureInfoString.append( "\n" ); - } - } - - if ( infoFormat == QLatin1String( "text/html" ) ) - { - featureInfoString.append( "
Feature" + featureElement.attribute( QStringLiteral( "id" ) ) + "
" + attributeElement.attribute( QStringLiteral( "name" ) ) + "" + attributeElement.attribute( QStringLiteral( "value" ) ) + "
\n
\n" ); - } - } - } - if ( infoFormat == QLatin1String( "text/plain" ) ) - { - featureInfoString.append( "\n" ); - } - else if ( infoFormat == QLatin1String( "text/html" ) ) - { - featureInfoString.append( "\n

\n" ); - - } - } - if ( infoFormat == QLatin1String( "text/html" ) ) - { - featureInfoString.append( "\n" ); - } - ba = featureInfoString.toUtf8(); - } - else //unsupported format, set exception - { - setServiceException( QgsMapServiceException( QStringLiteral( "InvalidFormat" ), "Feature info format '" + infoFormat + "' is not supported. Possibilities are 'text/plain', 'text/html' or 'text/xml'." ) ); - return; - } - - setHttpResponse( ba, infoFormat ); -} - void QgsRequestHandler::setServiceException( const QgsMapServiceException& ex ) { // Safety measure to avoid potential leaks if called repeatedly @@ -378,15 +193,6 @@ void QgsRequestHandler::setServiceException( const QgsMapServiceException& ex ) setHttpResponse( ba, QStringLiteral( "text/xml" ) ); } -void QgsRequestHandler::setGetPrintResponse( QByteArray* ba ) -{ - if ( ba ) - { - setHttpResponse( *ba, formatToMimeType( mFormat ) ); - } -} - - bool QgsRequestHandler::startGetFeatureResponse( QByteArray* ba, const QString& infoFormat ) { if ( !ba ) @@ -608,296 +414,3 @@ void QgsRequestHandler::removeParameter( const QString &key ) } -void QgsRequestHandler::medianCut( QVector& colorTable, int nColors, const QImage& inputImage ) -{ - QHash inputColors; - imageColors( inputColors, inputImage ); - - if ( inputColors.size() <= nColors ) //all the colors in the image can be mapped to one palette color - { - colorTable.resize( inputColors.size() ); - int index = 0; - QHash::const_iterator inputColorIt = inputColors.constBegin(); - for ( ; inputColorIt != inputColors.constEnd(); ++inputColorIt ) - { - colorTable[index] = inputColorIt.key(); - ++index; - } - return; - } - - //create first box - QgsColorBox firstBox; //QList< QPair > - int firstBoxPixelSum = 0; - QHash::const_iterator inputColorIt = inputColors.constBegin(); - for ( ; inputColorIt != inputColors.constEnd(); ++inputColorIt ) - { - firstBox.push_back( qMakePair( inputColorIt.key(), inputColorIt.value() ) ); - firstBoxPixelSum += inputColorIt.value(); - } - - QgsColorBoxMap colorBoxMap; //QMultiMap< int, ColorBox > - colorBoxMap.insert( firstBoxPixelSum, firstBox ); - QMap::iterator colorBoxMapIt = colorBoxMap.end(); - - //split boxes until number of boxes == nColors or all the boxes have color count 1 - bool allColorsMapped = false; - while ( colorBoxMap.size() < nColors ) - { - //start at the end of colorBoxMap and pick the first entry with number of colors < 1 - colorBoxMapIt = colorBoxMap.end(); - while ( true ) - { - --colorBoxMapIt; - if ( colorBoxMapIt.value().size() > 1 ) - { - splitColorBox( colorBoxMapIt.value(), colorBoxMap, colorBoxMapIt ); - break; - } - if ( colorBoxMapIt == colorBoxMap.begin() ) - { - allColorsMapped = true; - break; - } - } - - if ( allColorsMapped ) - { - break; - } - else - { - continue; - } - } - - //get representative colors for the boxes - int index = 0; - colorTable.resize( colorBoxMap.size() ); - QgsColorBoxMap::const_iterator colorBoxIt = colorBoxMap.constBegin(); - for ( ; colorBoxIt != colorBoxMap.constEnd(); ++colorBoxIt ) - { - colorTable[index] = boxColor( colorBoxIt.value(), colorBoxIt.key() ); - ++index; - } -} - -void QgsRequestHandler::imageColors( QHash& colors, const QImage& image ) -{ - colors.clear(); - int width = image.width(); - int height = image.height(); - - const QRgb* currentScanLine = nullptr; - QHash::iterator colorIt; - for ( int i = 0; i < height; ++i ) - { - currentScanLine = ( const QRgb* )( image.scanLine( i ) ); - for ( int j = 0; j < width; ++j ) - { - colorIt = colors.find( currentScanLine[j] ); - if ( colorIt == colors.end() ) - { - colors.insert( currentScanLine[j], 1 ); - } - else - { - colorIt.value()++; - } - } - } -} - -void QgsRequestHandler::splitColorBox( QgsColorBox& colorBox, QgsColorBoxMap& colorBoxMap, - QMap::iterator colorBoxMapIt ) -{ - - if ( colorBox.size() < 2 ) - { - return; //need at least two colors for a split - } - - //a,r,g,b ranges - int redRange = 0; - int greenRange = 0; - int blueRange = 0; - int alphaRange = 0; - - if ( !minMaxRange( colorBox, redRange, greenRange, blueRange, alphaRange ) ) - { - return; - } - - //sort color box for a/r/g/b - if ( redRange >= greenRange && redRange >= blueRange && redRange >= alphaRange ) - { - qSort( colorBox.begin(), colorBox.end(), redCompare ); - } - else if ( greenRange >= redRange && greenRange >= blueRange && greenRange >= alphaRange ) - { - qSort( colorBox.begin(), colorBox.end(), greenCompare ); - } - else if ( blueRange >= redRange && blueRange >= greenRange && blueRange >= alphaRange ) - { - qSort( colorBox.begin(), colorBox.end(), blueCompare ); - } - else - { - qSort( colorBox.begin(), colorBox.end(), alphaCompare ); - } - - //get median - double halfSum = colorBoxMapIt.key() / 2.0; - int currentSum = 0; - int currentListIndex = 0; - - QgsColorBox::iterator colorBoxIt = colorBox.begin(); - for ( ; colorBoxIt != colorBox.end(); ++colorBoxIt ) - { - currentSum += colorBoxIt->second; - if ( currentSum >= halfSum ) - { - break; - } - ++currentListIndex; - } - - if ( currentListIndex > ( colorBox.size() - 2 ) ) //if the median is contained in the last color, split one item before that - { - --currentListIndex; - currentSum -= colorBoxIt->second; - } - else - { - ++colorBoxIt; //the iterator needs to point behind the last item to remove - } - - //do split: replace old color box, insert new one - QgsColorBox newColorBox1 = colorBox.mid( 0, currentListIndex + 1 ); - colorBoxMap.insert( currentSum, newColorBox1 ); - - colorBox.erase( colorBox.begin(), colorBoxIt ); - QgsColorBox newColorBox2 = colorBox; - colorBoxMap.erase( colorBoxMapIt ); - colorBoxMap.insert( halfSum * 2.0 - currentSum, newColorBox2 ); -} - -bool QgsRequestHandler::minMaxRange( const QgsColorBox& colorBox, int& redRange, int& greenRange, int& blueRange, int& alphaRange ) -{ - if ( colorBox.size() < 1 ) - { - return false; - } - - int rMin = INT_MAX; - int gMin = INT_MAX; - int bMin = INT_MAX; - int aMin = INT_MAX; - int rMax = INT_MIN; - int gMax = INT_MIN; - int bMax = INT_MIN; - int aMax = INT_MIN; - - int currentRed = 0; - int currentGreen = 0; - int currentBlue = 0; - int currentAlpha = 0; - - QgsColorBox::const_iterator colorBoxIt = colorBox.constBegin(); - for ( ; colorBoxIt != colorBox.constEnd(); ++colorBoxIt ) - { - currentRed = qRed( colorBoxIt->first ); - if ( currentRed > rMax ) - { - rMax = currentRed; - } - if ( currentRed < rMin ) - { - rMin = currentRed; - } - - currentGreen = qGreen( colorBoxIt->first ); - if ( currentGreen > gMax ) - { - gMax = currentGreen; - } - if ( currentGreen < gMin ) - { - gMin = currentGreen; - } - - currentBlue = qBlue( colorBoxIt->first ); - if ( currentBlue > bMax ) - { - bMax = currentBlue; - } - if ( currentBlue < bMin ) - { - bMin = currentBlue; - } - - currentAlpha = qAlpha( colorBoxIt->first ); - if ( currentAlpha > aMax ) - { - aMax = currentAlpha; - } - if ( currentAlpha < aMin ) - { - aMin = currentAlpha; - } - } - - redRange = rMax - rMin; - greenRange = gMax - gMin; - blueRange = bMax - bMin; - alphaRange = aMax - aMin; - return true; -} - -bool QgsRequestHandler::redCompare( QPair c1, QPair c2 ) -{ - return qRed( c1.first ) < qRed( c2.first ); -} - -bool QgsRequestHandler::greenCompare( QPair c1, QPair c2 ) -{ - return qGreen( c1.first ) < qGreen( c2.first ); -} - -bool QgsRequestHandler::blueCompare( QPair c1, QPair c2 ) -{ - return qBlue( c1.first ) < qBlue( c2.first ); -} - -bool QgsRequestHandler::alphaCompare( QPair c1, QPair c2 ) -{ - return qAlpha( c1.first ) < qAlpha( c2.first ); -} - -QRgb QgsRequestHandler::boxColor( const QgsColorBox& box, int boxPixels ) -{ - double avRed = 0; - double avGreen = 0; - double avBlue = 0; - double avAlpha = 0; - QRgb currentColor; - int currentPixel; - - double weight; - - QgsColorBox::const_iterator colorBoxIt = box.constBegin(); - for ( ; colorBoxIt != box.constEnd(); ++colorBoxIt ) - { - currentColor = colorBoxIt->first; - currentPixel = colorBoxIt->second; - weight = ( double )currentPixel / boxPixels; - avRed += ( qRed( currentColor ) * weight ); - avGreen += ( qGreen( currentColor ) * weight ); - avBlue += ( qBlue( currentColor ) * weight ); - avAlpha += ( qAlpha( currentColor ) * weight ); - } - - return qRgba( avRed, avGreen, avBlue, avAlpha ); -} - - diff --git a/src/server/qgsrequesthandler.h b/src/server/qgsrequesthandler.h index ecb1489d688..d55c2d33133 100644 --- a/src/server/qgsrequesthandler.h +++ b/src/server/qgsrequesthandler.h @@ -54,17 +54,9 @@ class SERVER_EXPORT QgsRequestHandler explicit QgsRequestHandler( QgsServerRequest& request, QgsServerResponse& response ); ~QgsRequestHandler(); - /** Sends the map image back to the client - * @note not available in Python bindings - */ - void setGetMapResponse( const QString& service, QImage* img, int imageQuality ); - //! @note not available in Python bindings void setGetCapabilitiesResponse( const QDomDocument& doc ); - //! @note not available in Python bindings - void setGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ); - //! Allow plugins to return a QgsMapServiceException void setServiceException( const QgsMapServiceException &ex ); @@ -74,9 +66,6 @@ class SERVER_EXPORT QgsRequestHandler //! @note not available in Python bindings void setXmlResponse( const QDomDocument& doc, const QString& mimeType ); - //! @note not available in Python bindings - void setGetPrintResponse( QByteArray* ba ); - //! @note not available in Python bindings bool startGetFeatureResponse( QByteArray* ba, const QString& infoFormat ); @@ -160,19 +149,6 @@ class SERVER_EXPORT QgsRequestHandler void setupParameters(); - static void medianCut( QVector& colorTable, int nColors, const QImage& inputImage ); - static void imageColors( QHash& colors, const QImage& image ); - static void splitColorBox( QgsColorBox& colorBox, QgsColorBoxMap& colorBoxMap, - QMap::iterator colorBoxMapIt ); - static bool minMaxRange( const QgsColorBox& colorBox, int& redRange, int& greenRange, int& blueRange, int& alphaRange ); - static bool redCompare( QPair c1, QPair c2 ); - static bool greenCompare( QPair c1, QPair c2 ); - static bool blueCompare( QPair c1, QPair c2 ); - static bool alphaCompare( QPair c1, QPair c2 ); - //! Calculates a representative color for a box (pixel weighted average) - static QRgb boxColor( const QgsColorBox& box, int boxPixels ); - // TODO: if HAVE_SERVER_PYTHON - //! This is set by the parseInput methods of the subclasses (parameter FORMAT, e.g. 'FORMAT=PNG') QString mFormat; QString mFormatString; //format string as it is passed in the request (with base)