How to style transparent overlayed WMS layer
Asked Answered
L

3

4

I successfully overlayed a WMS layer in google maps v3, however, as the information on tiles is black on transparent, it is not well seen on dark background (like satellite map), see some tile for example:

http://geoportal2.uhul.cz/wms_oprl/?SERVICE=WMS&REQUEST=GetMap&SERVICE=WMS&VERSION=1.1.1&LAYERS=HMLCR&FORMAT=image/png;%20mode=24bit&FGCOLOR=0xFF0000&TRANSPARENT=TRUE&SRS=EPSG:4326&BBOX=16.58935546875,49.37522008143603,16.600341796875,49.38237278700955&WIDTH=256&HEIGHT=256&STYLES=

(This was the WMS link to retrieve that tile)

Question: how to modify the above WMS request to change the foreground color (currently black) to some custom color (e.g. red)? In other words, how to style the layer? The server is apparently able to do it for this layer, since it is possible to do it via their web map application (which works in IE only), where you can select the color. See this map image for example:

enter image description here

(The following link was used to retrieve the image - note that it contains scale and logo, so it's not a proper tile.)

Unfortunatelly, this web application doesn't use WMS to get this styled map so I can't just copy the styling parameters to WMS request. I must do the styling via the WMS request (because this other request format is proprietary, retrieves whole map - not designed for tiles - and it doesn't seem to support WGS coordinates) - how shall I do it?

I tried to:

  1. look at the WMS documentation, especially version 1.1.1
  2. look at the SLDs, but it seems pretty complex thing to grasp...
  3. look at the GetCapabilites command output for the WMS server
  4. Also, having look at DescribeLayer and GetStyles command outputs for my desired layer (HLMCR) I don't even know if this layer will support styling over WMS...

I got lost, I'd be grateful if you point me to the right direction - or information if it's even solvable in WMS (for this layer).

"It's not possible" is also a useful answer for me!

Thanks in advance.

Latoria answered 30/11, 2011 at 2:43 Comment(2)
As a WMS is a service that turns spatial data into an image, you must provide the service with a style to do the rendering and send that image back to you in the response; SLD is the way to go here. You can create your own style, then send a request with that style attached, either using the SLD_BODY parameter, or the SLD parameter pointing to a URL with that SLD style at the end of it.Tyr
The service mentioned doesn't seem to exist any more, which of the following services provides a similar layer (Czech not my strong point): http://geoportal.uhul.cz/wms_mysl/service.svc/get?request=GetCapabilities&service=WMS& or http://geoportal.uhul.cz/wms_oprl/service.svc/get?request=GetCapabilities&service=WMS&Tyr
M
2

At first glance, it looks like this is a Mapserver 5.x implementation, and getCapabilities notes that UserDefinedSymbolization SupportSLD="1" is enabled at the Map level, which IIRC means that all Layers should inherit it.

So in theory you should be able to supply SLD either in the GET request or in a file somewhere and supply the URL of your SLD to the GET request, and be all set.

Writing the SLD will be the annoying bit, but if you think you have some SLD that should work but doesn't, paste it here.

Monopolist answered 4/1, 2012 at 2:7 Comment(1)
thanks jlivni. Do you have some simple example, that could be easily rewritten for my purpose? I need to change just one color of one property (foreground color). And how to get the name of this property which is used to refer it in SLD. ThanksLatoria
F
0

Use a wrapper script that reads the image from the WMS and recolorizes it:

Wrapper

Here is an example written in PHP:

<?php
$url = $_GET['url'];
$im = imagecreatefrompng($url);

if($im && imagefilter($im, IMG_FILTER_COLORIZE, 255, 0, 0, 0)){
    // this line is only needed if original image has transparency (32bit/pixel)
    // and you want to preserve that transparency
    imagesavealpha($im, true);

    header('Content-type: image/png');
    imagepng($im);
}else{
    echo 'Conversion failed.';
}

imagedestroy($im);
exit;
?>

Then instead of calling your WMS link, you call the wrapper and pass the WMS link as a parameter (recolor_png.php?url=...). The wrapper reads the original image and returns a new PNG with a colorized version. Don't forget that the link that you pass as a parameter must be urlencoded to work correctly (all special characters replaced by their %XX hex notation). In JavaScript you can do that using the encodeURIComponent() method.

Here is a working example using your link and the above wrapper on my server:

http://www.digilog.de/pub/stackoverflow/recolor_png2.php?url=http%3A%2F%2Fgeoportal2.uhul.cz%2Fwms_oprl%2F%3FSERVICE%3DWMS%26REQUEST%3DGetMap%26SERVICE%3DWMS%26VERSION%3D1.1.1%26LAYERS%3DHMLCR%26FORMAT%3Dimage%2Fpng%3B%2520mode%3D24bit%26FGCOLOR%3D0xFF0000%26TRANSPARENT%3DTRUE%26SRS%3DEPSG%3A4326%26BBOX%3D16.58935546875%2C49.37522008143603%2C16.600341796875%2C49.38237278700955%26WIDTH%3D256%26HEIGHT%3D256%26STYLES%3D

This is the resulting image (semi-transparent version):

recolor_png2.png
(source: digilog.de)

The same wrapper without semi-transparent output (imagesavealpha deleted from code):

http://www.digilog.de/pub/stackoverflow/recolor_png.php?url=http%3A%2F%2Fgeoportal2.uhul.cz%2Fwms_oprl%2F%3FSERVICE%3DWMS%26REQUEST%3DGetMap%26SERVICE%3DWMS%26VERSION%3D1.1.1%26LAYERS%3DHMLCR%26FORMAT%3Dimage%2Fpng%3B%2520mode%3D24bit%26FGCOLOR%3D0xFF0000%26TRANSPARENT%3DTRUE%26SRS%3DEPSG%3A4326%26BBOX%3D16.58935546875%2C49.37522008143603%2C16.600341796875%2C49.38237278700955%26WIDTH%3D256%26HEIGHT%3D256%26STYLES%3D

And the resulting non-transparent image:

recolor_png.png
(source: digilog.de)

I will leave that wrappers online for some days for you to test.

Caching

As this conversion is processor intensive, it might be wise to add some caching code to the wrapper:

  • create a hash code from the give URL, e.g.: $hash=md5($url)
  • check whether an image named $hash.png exists in a storage subfolder
  • if so: read the image from file and return it
  • otherwise: create image, save it as $hash.png in subfolder and also return it immediately

If you expect your WMS content to change over time: Also check the creation date of cached images and purge them if they are too old (like a month or so). So any changes to the WMS maps will ripple into your system after a maximum time of one month.

Farl answered 30/11, 2011 at 23:57 Comment(7)
Hi @Jpspy! Thanks for your answer! This is of course not an ideal solution because of increased latency but it's fairly simple and elegant so it's a nice "salvage solution" for me if everything other fails - thanks! I've generated the image and added it to your answer. There is a little problem with antialiasing not being converted correctly - there are residual hints of black color. Maybe because it's PNG and the antialiasing is semi-transparent. Would you know how to change the hue of the whole image? I think that would help. Thanks!Latoria
I found something but going pixel by pixel would be very slow for recoloring map tiles... ideal would be to call one php function for this like you did.Latoria
No problem. If your original image is transparent you have to add one more line to the code to activate transparent PNG output: imagesavealpha($im, true); after the line $im = imagecreatefrompng($url);. I will add that to the code above and add a second wrapper.Farl
Thanks! There are still small hints of black (try to zoom out, Ctrl+ in mozilla). Do you have idea why?Latoria
Nope. Looks actually like a PHP bug. You can bleed the red a little bit more by using imagefilter($im, IMG_FILTER_COLORIZE, 255, -255, -255). But basically all semi-transparent edges have a strange tint of black.Farl
"But basically all semi-transparent edges have a strange tint of black" - no, that's not normal. That's a bug.Latoria
though this is not a real solution, it is the only reasonable answer up to now - bounty goes to you.Latoria
E
-1

The WMS link already has some custom params that allow you to do exactly what you ask for. The link is the following:

  http://geoportal2.uhul.cz/mapserv/php/mapserv3.php?project=oprl_2011&mode=map&mapsize=256%20256&layers=HMLCR%20&x=1322616184548&map_SMO_class_0_color=0%200%200&map_HMLCR_class_0_color=255%200%200&mapext=-679915.1258015268%20-1062651.2224427482%20-679660.3694656485%20-1062461.062442748

If you inspect it you will notice that between all the url encoded parameters there is a parameter interestingly called: map_HMLCR_class_0_color

If you change its value to, say green (whose RGB code is 0,255,0), the layers are rendered in green. The color is expressed as an RGB code. There is also another parameter map_SMO_class_0_color but I don't understand what that does. Perhaps it styles some feature which is not visible in that request?

Example for green color:

 http://geoportal2.uhul.cz/mapserv/php/mapserv3.php?project=oprl_2011&mode=map&mapsize=256%20256&layers=HMLCR%20&x=1322616184548&map_SMO_class_0_color=0%20100%20200&map_HMLCR_class_0_color=0%20255%200&mapext=-679915.1258015268%20-1062651.2224427482%20-679660.3694656485%20-1062461.062442748

which produces the following:

green styled request

A note con rgb color representation in Mapserver

the RGB triplet must be written as follows in the request:

R G B

(note that the blanks are required). Whose URl encoded representation is:

R%20G%20B

because %20 is how space is encoded in URLs.

Eggers answered 3/12, 2011 at 10:37 Comment(1)
Hi unicoletti, this is not the WMS link! This is another request interface on the server which retrieves complete map. I know I can do this, as you can see in my question I already posted an example how to color the layer in red! I'm looking for a way how to do this using WMS.Latoria

© 2022 - 2024 — McMap. All rights reserved.