Skip to content
Permalink
Browse files

[Bugfix][Regression][Server] JPEG output for WMS GetPrint request has…

… gone

In QGIS Server 2.* the WMS GetPrint request could genrate JPEG image. QGIS Server 3.4 has lost this capabilities.
```
<ServiceExceptionReport xmlns="http://www.opengis.net/ogc" version="1.3.0" capture-installed="true">
    <ServiceException code="InvalidFormat">
        Output format jpg is not supported by the GetPrint request
    </ServiceException>
</ServiceExceptionReport>
```
To fix this regression, it is necessary to accept JPEG output format.

And to avoid this regression to come back, the QGIS Server tests has been updated to accept jpg image test.
  • Loading branch information
rldhont committed Mar 19, 2019
1 parent 1e8aec4 commit 547fd683d95acf4a4a45fcfc07ee60daedb66cfb
@@ -35,22 +35,24 @@ namespace QgsWms
QString contentType;

// GetPrint supports svg/png/pdf
if ( format == QgsWmsParameters::PNG )
switch ( format )
{
contentType = "image/png";
}
else if ( format == QgsWmsParameters::SVG )
{
contentType = "image/svg+xml";
}
else if ( format == QgsWmsParameters::PDF )
{
contentType = "application/pdf";
}
else
{
throw QgsServiceException( QStringLiteral( "InvalidFormat" ),
QString( "Output format %1 is not supported by the GetPrint request" ).arg( wmsParameters.formatAsString() ) );
case QgsWmsParameters::PNG:
contentType = QStringLiteral( "image/png" );
break;
case QgsWmsParameters::JPG:
contentType = QStringLiteral( "image/jpeg" );
break;
case QgsWmsParameters::SVG:
contentType = QStringLiteral( "image/svg+xml" );
break;
case QgsWmsParameters::PDF:
contentType = QStringLiteral( "application/pdf" );
break;
default:
throw QgsServiceException( QStringLiteral( "InvalidFormat" ),
QString( "Output format %1 is not supported by the GetPrint request" ).arg( wmsParameters.formatAsString() ) );
break;
}

response.setHeader( QStringLiteral( "Content-Type" ), contentType );
@@ -514,7 +514,7 @@ namespace QgsWms
exporter.exportToSvg( tempOutputFile.fileName(), exportSettings );
}
}
else if ( format == QgsWmsParameters::PNG )
else if ( format == QgsWmsParameters::PNG || format == QgsWmsParameters::JPG )
{
// Settings for the layout exporter
QgsLayoutExporter::ImageExportSettings exportSettings;
@@ -176,12 +176,20 @@ def _result(self, data):

return data[1], headers

def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize()):
temp_image = os.path.join(tempfile.gettempdir(), "%s_result.png" % control_image)
def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize(), outputJpg=False):

extFile = 'png'
if outputJpg:
extFile = 'jpg'

temp_image = os.path.join(tempfile.gettempdir(), "%s_result.%s" % (control_image, extFile))

with open(temp_image, "wb") as f:
f.write(image)

if outputJpg:
return (True, "QgsRenderChecker can't be used for JPG images")

control = QgsRenderChecker()
control.setControlPathPrefix("qgis_server")
control.setControlName(control_image)
@@ -190,35 +198,41 @@ def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize()):
control.setSizeTolerance(max_size_diff.width(), max_size_diff.height())
return control.compareImages(control_image, max_diff), control.report()

def _img_diff_error(self, response, headers, image, max_diff=100, max_size_diff=QSize(), unittest_data_path='control_images'):
def _img_diff_error(self, response, headers, image, max_diff=100, max_size_diff=QSize(), unittest_data_path='control_images', outputJpg=False):

extFile = 'png'
contentType = 'image/png'
if outputJpg:
extFile = 'jpg'
contentType = 'image/jpeg'

reference_path = unitTestDataPath(unittest_data_path) + '/qgis_server/' + image + '/' + image + '.png'
reference_path = unitTestDataPath(unittest_data_path) + '/qgis_server/' + image + '/' + image + '.' + extFile
self.store_reference(reference_path, response)

self.assertEqual(
headers.get("Content-Type"), "image/png",
"Content type is wrong: %s\n%s" % (headers.get("Content-Type"), response))
headers.get("Content-Type"), contentType,
"Content type is wrong: %s instead of %s\n%s" % (headers.get("Content-Type"), contentType, response))

test, report = self._img_diff(response, image, max_diff, max_size_diff)
test, report = self._img_diff(response, image, max_diff, max_size_diff, outputJpg)

with open(os.path.join(tempfile.gettempdir(), image + "_result.png"), "rb") as rendered_file:
with open(os.path.join(tempfile.gettempdir(), image + "_result." + extFile), "rb") as rendered_file:
encoded_rendered_file = base64.b64encode(rendered_file.read())
if not os.environ.get('ENCODED_OUTPUT'):
message = "Image is wrong\: rendered file %s/%s_result.png" % (tempfile.gettempdir(), image)
message = "Image is wrong\: rendered file %s/%s_result.%s" % (tempfile.gettempdir(), image, extFile)
else:
message = "Image is wrong\n%s\nImage:\necho '%s' | base64 -d >%s/%s_result.png" % (
report, encoded_rendered_file.strip().decode('utf8'), tempfile.gettempdir(), image
message = "Image is wrong\n%s\nImage:\necho '%s' | base64 -d >%s/%s_result.%s" % (
report, encoded_rendered_file.strip().decode('utf8'), tempfile.gettempdir(), image, extFile
)

# If the failure is in image sizes the diff file will not exists.
if os.path.exists(os.path.join(tempfile.gettempdir(), image + "_result_diff.png")):
with open(os.path.join(tempfile.gettempdir(), image + "_result_diff.png"), "rb") as diff_file:
if os.path.exists(os.path.join(tempfile.gettempdir(), image + "_result_diff." + extFile)):
with open(os.path.join(tempfile.gettempdir(), image + "_result_diff." + extFile), "rb") as diff_file:
if not os.environ.get('ENCODED_OUTPUT'):
message = "Image is wrong\: diff file %s/%s_result_diff.png" % (tempfile.gettempdir(), image)
message = "Image is wrong\: diff file %s/%s_result_diff.%s" % (tempfile.gettempdir(), image, extFile)
else:
encoded_diff_file = base64.b64encode(diff_file.read())
message += "\nDiff:\necho '%s' | base64 -d > %s/%s_result_diff.png" % (
encoded_diff_file.strip().decode('utf8'), tempfile.gettempdir(), image
message += "\nDiff:\necho '%s' | base64 -d > %s/%s_result_diff.%s" % (
encoded_diff_file.strip().decode('utf8'), tempfile.gettempdir(), image, extFile
)

self.assertTrue(test, message)
@@ -202,8 +202,13 @@ def _post_restricted(self, data, query_string=None):
self._server.putenv("QGIS_PROJECT_FILE", '')
return result

def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize()):
temp_image = os.path.join(tempfile.gettempdir(), "%s_result.png" % control_image)
def _img_diff(self, image, control_image, max_diff, max_size_diff=QSize(), outputJpg=False):

extFile = 'png'
if outputJpg:
extFile = 'jpg'

temp_image = os.path.join(tempfile.gettempdir(), "%s_result.%s" % (control_image, extFile))

with open(temp_image, "wb") as f:
f.write(image)
@@ -90,6 +90,22 @@ def test_wms_getprint_basic(self):
r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetPrint_Basic")

# Output JPEG
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"FORMAT": "jpeg",
"map0:EXTENT": "-33626185.498,-13032965.185,33978427.737,16020257.031",
"LAYERS": "Country,Hello",
"CRS": "EPSG:3857"
}.items())])

r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetPrint_Basic", outputJpg=True)

def test_wms_getprint_style(self):
# default style
qs = "?" + "&".join(["%s=%s" % i for i in list({
Binary file not shown.

0 comments on commit 547fd68

Please sign in to comment.
You can’t perform that action at this time.