How can I smoothen the (GIF)-output of the mapserver
Camden Daily
cdaily at GMAIL.COM
Tue Apr 26 07:32:41 PDT 2005
After playing around with antialiasing a lot, I found that what worked
best for me was to just use a function after I've configured my map
that would use the php image handling functions to draw the image at a
larger size and then scale it down to the original size, antialiasing
as it went. I found in doing it that way, though, that the text would
get a little blurred out. So I then decided to render my labels as a
seperate image and just superimpose them over my antialiased map. The
results have been quite good.
First off, for image handling in php, you'll need to configure php
--with-gd=/path/to/gd. It's important to make sure that the version
of gd you configure it with is the same version as the one you
compiled mapserver with. Also, just specifying --with-gd, and not
including the path, will make php revert to using it's own bundled gd
(probably not what you want). If you have problems with this step,
search the archvies; there's been plenty of discussions about it.
I wrote a function to call at the end of my mapscript like this:
$image_url = antialias(2);
where 2 is the scale factor. Increasing the scale makes the image
look better, but also slows it down a bit.
Here's the function. It should be relatively self-explanatory. I
posted an older version of this function maybe a month back, but it's
had some bug fixes since then.
///////////////////////////////////////////////////////////////
//
// function antialias()
//
// draws our map at a larger size, then samples it back down to provide
// antialiasing. annotation layers and the scalebar are drawn seperately
// and combined over the resulting image, so that they are not distroted.
//
// using this function, all labels must be drawn as seperate annotation layers.
//
// the .map file should be configured to output as png for transparency.
//
///////////////////////////////////////////////////////////////
function antialias($scale) {
global $map, $root_directory;
// get the dimensions of the image
$image_width = $map->width;
$image_height = $map->height;
// scale the map up
$map->set("width", $image_width * $scale);
$map->set("height", $image_height * $scale);
// turn off the scalebar if there is one
$scalebar_present = false;
$scalebar = $map->scalebar;
if ($scalebar->status == MS_EMBED) {
$scalebar->set("status", MS_OFF);
$scalebar_present = true;
}
// loop through our layers, and if it's status is on, loop through
the classes scaling the sizes
$scaled_symbols = array();
for ($i=0; $i < $map->numlayers; $i++) {
$layer = $map->getLayer($i);
if ($layer->status == MS_ON AND $layer->type != MS_LAYER_ANNOTATION) {
for ($j=0; $j < $layer->numclasses; $j++) {
$class = $layer->getClass($j);
for ($k=0; $k < $class->numstyles; $k++) {
$style = $class->getStyle($k);
// scale the size and offsets
$style->set("size", $style->size * $scale);
$style->set("offsetx", $style->offsetx * $scale);
$style->set("offsety", $style->offsety * $scale);
// for symbols with styles them, we need to scale those as well
$symbol_id = $style->symbol;
$symbol = $map->getsymbolobjectbyid($symbol_id);
$already_scaled = false;
reset($scaled_symbols);
foreach ($scaled_symbols as $scaled) {
if ($scaled == $symbol->name) {
$already_scaled = true;
}
}
if (!$already_scaled) {
array_push($scaled_symbols, $symbol->name);
$points = $scaled_points = $symbol->getstylearray();
if (count($points) > 1) {
for ($l=0; $l < count($points); $l++) {
$scaled_points[$l] = $points[$l] * $scale;
}
$symbol->setstyle($scaled_points);
}
}
}
}
}
}
// loop through and turn off our annotation layers for now, keeping
track of them
$labels = array();
for ($i=0; $i < $map->numlayers; $i++) {
$layer = $map->getLayer($i);
if ($layer->type == MS_LAYER_ANNOTATION AND $layer->status == MS_ON) {
array_push($labels, $layer);
$layer->set("status", MS_OFF);
}
}
// draw our image
$image = $map->draw();
$image_url = $image->saveWebImage('MS_PNG', 1, 1, 0);
// create our image objects
$old = imagecreatefrompng($root_directory . $image_url);
$new = imagecreatetruecolor($image_width, $image_height);
// the background color gets dropped from our transparent pngs, so
start by filling our new image with it
$back_color = $map->imagecolor;
$back_color = imagecolorallocate($new, $back_color->red,
$back_color->green, $back_color->blue);
imagefill($new, 0, 0, $back_color);
// resample the image back down to the original size (antialiasing it)
imagecopyresampled($new, $old, 0, 0, 0, 0, $image_width,
$image_height, $image_width * $scale, $image_height * $scale);
// scale the map down
$map->set("width", $image_width);
$map->set("height", $image_height);
// flip off all layers on the map
for ($i=0; $i < $map->numlayers; $i++) {
$layer = $map->getLayer($i);
$layer->set("status", MS_OFF);
}
// flip on those annotation layers we turned off earlier
for ($i=0; $i < count($labels); $i++) {
$labels[$i]->set("status", MS_ON);
}
// turn the scalebar back on
if ($scalebar_present) {
$scalebar->set("status", MS_EMBED);
}
// draw our image again, this time with just the annotations
$label_image = $map->draw();
$label_url = $label_image->saveWebImage('MS_PNG', 1, 1, 0);
// merge the text from our new image over the old one
$old = imagecreatefrompng($root_directory . $label_url);
imagecopyresampled($new, $old, 0, 0, 0, 0, $image_width,
$image_height, $image_width, $image_height);
// change our filename extention from .png to .jpg
$image_url = substr($image_url, 0, -3) . "jpg";
// save our new image
imagejpeg($new, $root_directory . $image_url);
// free up memory
imagedestroy($im);
imagedestroy($new);
// return the location of our new image
return $image_url;
}
On 4/26/05, Wolfgang Qual <Wolfgang.Qual at muenchen.de> wrote:
> Devinitively! If you could give some examples / how-to's I would be very
> glad. I am curious about it.
>
> Regards,
> Wolfgang
>
> Camden Daily schrieb:
>
> > I believe what you're looking for is antialiasing, in order to make
> > things like lines less pixelated. Antialiasing is available for text
> > and a few of the symbol types, but I had more luck taking the advise
> > of some on the listserve and using php/mapscript to actually draw the
> > maps at a larger scale and then letting php resample the image down to
> > the final size, antialiasing in the process.
> >
> > If you're interested in some of the details for that method, let me
> > know and I'll post some stuff.
> >
> > -Camden Daily
> > Prudential Preferred Properties
> > http://www.prupref.com
> >
> > On 4/25/05, Wolfgang Qual <Wolfgang.Qual at muenchen.de> wrote:
> >
> >>Hello list,
> >>When I create a mapserver-map, I sometimes have the impression that the
> >>maps look quite square-edged. Especially, if the color contrast of
> >>certain themes is high (b/w.). That's the reason why I am looking for a
> >>way to smoothen the output-GIFs of the mapserver - just something like
> >>the blur-filtering in Photoshop or GIMP...
> >>
> >>Thanks,
> >>
> >>Wolfgang
> >>
> >
> >
>
> --
> Wolfgang Qual
> Landeshauptstadt München
> Referat für Gesundheit und Umwelt
> RGU-UW 11
> Sg. 1 Gesundheits- und Umweltberichterstattung,
> Energie und Klimaschutz
> Bayerstr. 28a, 80335 München
> Tel.: +49 (0)89 233-477 17
> Fax.: +49 (0)89 233-477 05
> E-Mail: wolfgang.qual at muenchen.de
>
More information about the MapServer-users
mailing list