# modifying a line function to support dotted lines

Hi guys,

In a previous question of mine RQuadline gave me a lovely Function which allows me to draw lines, specify the color and width.

I would like to modify the function so that when it is called, an extra parameter is sent to specify if it is to draw a dotted, or a solid line, but I want to keep the ability to specify the thickness.

Here's the code I have at the moment from RQuadling:

<?php
function imagelinethick(\$image, \$x1, \$y1, \$x2, \$y2, \$color, \$thick = 1)
{
/* this way it works well only for orthogonal lines
imagesetthickness(\$image, \$thick);
return imageline(\$image, \$x1, \$y1, \$x2, \$y2, \$color);
*/
if (\$thick == 1) {
return imageline(\$image, \$x1, \$y1, \$x2, \$y2, \$color);
}
\$t = \$thick / 2 - 0.5;
if (\$x1 == \$x2 || \$y1 == \$y2) {
return imagefilledrectangle(\$image, round(min(\$x1, \$x2) - \$t), round(min(\$y1, \$y2) - \$t), round(max(\$x1, \$x2) + \$t), round(max(\$y1, \$y2) + \$t), \$color);
}
\$k = (\$y2 - \$y1) / (\$x2 - \$x1); //y = kx + q
\$a = \$t / sqrt(1 + pow(\$k, 2));
\$points = array(
round(\$x1 - (1+\$k)*\$a), round(\$y1 + (1-\$k)*\$a),
round(\$x1 - (1-\$k)*\$a), round(\$y1 - (1+\$k)*\$a),
round(\$x2 + (1+\$k)*\$a), round(\$y2 - (1-\$k)*\$a),
round(\$x2 + (1-\$k)*\$a), round(\$y2 + (1+\$k)*\$a),
);
imagefilledpolygon(\$image, \$points, 4, \$color);
return imagepolygon(\$image, \$points, 4, \$color);
}

\$image = imagecreate(100, 100);
\$black = imagecolorallocate(\$image, 0, 0, 0);
\$white = imagecolorallocate(\$image, 255, 255, 255);
imagelinethick(\$image, 0, 0, 99, 99, \$white, 6);
imagepng(\$image);
imagedestroy(\$image);
?>

Cheers guys!
LVL 4
###### Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x

Senior Software DeveloperCommented:
<?php
function imagelinethick(\$image, \$x1, \$y1, \$x2, \$y2, \$color, \$thick = 1, \$a_style = NULL)
{
/*
this way it works well only for orthogonal lines
imagesetthickness(\$image, \$thick);
return imageline(\$image, \$x1, \$y1, \$x2, \$y2, \$color);
*/

if (!is_null(\$a_style))
{
imagesetstyle(\$image, \$a_style);
}

if (\$thick == 1)
{
return imageline(\$image, \$x1, \$y1, \$x2, \$y2, (!is_null(\$a_style) ? IMG_COLOR_STYLED : \$color));
}

\$t = \$thick / 2 - 0.5;
if (\$x1 == \$x2 || \$y1 == \$y2)
{
return imagefilledrectangle(\$image, round(min(\$x1, \$x2) - \$t), round(min(\$y1, \$y2) - \$t), round(max(\$x1, \$x2) + \$t), round(max(\$y1, \$y2) + \$t), (!is_null(\$a_style) ? IMG_COLOR_STYLED : \$color));
}

\$k = (\$y2 - \$y1) / (\$x2 - \$x1); //y = kx + q
\$a = \$t / sqrt(1 + pow(\$k, 2));
\$points = array
(
round(\$x1 - (1+\$k)*\$a), round(\$y1 + (1-\$k)*\$a),
round(\$x1 - (1-\$k)*\$a), round(\$y1 - (1+\$k)*\$a),
round(\$x2 + (1+\$k)*\$a), round(\$y2 - (1-\$k)*\$a),
round(\$x2 + (1-\$k)*\$a), round(\$y2 + (1+\$k)*\$a),
);
return imagefilledpolygon(\$image, \$points, 4, (!is_null(\$a_style) ? IMG_COLOR_STYLED : \$color));
}

/*
\$size = 100;
\$image = imagecreate(\$size, \$size);
\$black = imagecolorallocate(\$image, 0, 0, 0);
\$white = imagecolorallocate(\$image, 255, 255, 255);
\$a_style = array(\$white, \$white, \$white, \$white, \$white, \$black, \$black, \$black, \$black, \$black);

imagelinethick(\$image, 0, 0, \$size, \$size, \$white, 9, \$a_style);
imagepng(\$image);
imagedestroy(\$image);
*/

\$image = imagecreate(48, 48);
\$gray = imagecolorallocate(\$image, 192, 192, 192);
\$black = imagecolorallocate(\$image, 0, 0, 0);
\$color = array(255,255,255);
if (isset(\$_GET['color']) && (\$_GET['color'] != ''))
{
\$color = HexToRGB(\$_GET['color']);
}
\$line = imagecolorallocate(\$image, \$color[0], \$color[1], \$color[2]);
\$a_style = NULL;
if (isset(\$_GET['style']) && (\$_GET['style'] == 'dotted'))
{
\$a_style = array
(
\$line,
\$gray,
\$line,
\$gray,
\$line
);
}

imagelinethick(\$image, 5, 43, 43, 5, \$line, 4, \$a_style);
imageline(\$image, 0, 0, 0, 47, \$black);
imageline(\$image, 0, 0, 47, 0, \$black);
imageline(\$image, 47, 0, 47, 47, \$black);
imageline(\$image, 0, 47, 47, 47, \$black);
imagepng(\$image);
imagedestroy(\$image);
?>

With a url which has ?style=dotted, I get a dotted line.

The style has to include on/off sort of pattern.

Try ...

if (isset(\$_GET['style']) && (\$_GET['style'] == 'dotted'))
{
\$a_style = array
(
\$line,
\$gray,
);
}

also.
0

Senior Software DeveloperCommented:
<?php
function imagelinethick(\$image, \$x1, \$y1, \$x2, \$y2, \$color, \$thick = 1, \$a_style = NULL)
{
/* this way it works well only for orthogonal lines
imagesetthickness(\$image, \$thick);
return imageline(\$image, \$x1, \$y1, \$x2, \$y2, \$color);
*/

if (!is_null(\$a_style))
{
imagesetstyle(\$image, \$a_style);
}

if (\$thick == 1) {
return @imageline(\$image, \$x1, \$y1, \$x2, \$y2, (!is_null(\$a_style) ? IMG_COLOR_STYLED : \$color));
}
\$t = \$thick / 2 - 0.5;
if (\$x1 == \$x2 || \$y1 == \$y2) {
return imagefilledrectangle(\$image, round(min(\$x1, \$x2) - \$t), round(min(\$y1, \$y2) - \$t), round(max(\$x1, \$x2) + \$t), round(max(\$y1, \$y2) + \$t), (!is_null(\$a_style) ? IMG_COLOR_STYLED : \$color));
}

\$k = (\$y2 - \$y1) / (\$x2 - \$x1); //y = kx + q
\$a = \$t / sqrt(1 + pow(\$k, 2));
\$points = array(
round(\$x1 - (1+\$k)*\$a), round(\$y1 + (1-\$k)*\$a),
round(\$x1 - (1-\$k)*\$a), round(\$y1 - (1+\$k)*\$a),
round(\$x2 + (1+\$k)*\$a), round(\$y2 - (1-\$k)*\$a),
round(\$x2 + (1-\$k)*\$a), round(\$y2 + (1+\$k)*\$a),
);
return imagefilledpolygon(\$image, \$points, 4, (!is_null(\$a_style) ? IMG_COLOR_STYLED : \$color));
}

\$image = imagecreate(100, 100);
\$black = imagecolorallocate(\$image, 0, 0, 0);
\$white = imagecolorallocate(\$image, 255, 255, 255);
\$a_style = array(\$white, \$white, \$white, \$white, \$white, \$black, \$black, \$black, \$black, \$black);

imagelinethick(\$image, 0, 0, 99, 99, \$white, 6, \$a_style);
imagepng(\$image);
imagedestroy(\$image);
?>

results in a slightly odd line along the bottom. As this code is all grabbed from the manual (with my mods), I'm not too sure what is not working correctly. Yet.
0

Senior Software DeveloperCommented:
Fixed.

Instead of line being from 0,0 to 99,99, line is from 0,0 to 100,100;

<?php
function imagelinethick(\$image, \$x1, \$y1, \$x2, \$y2, \$color, \$thick = 1, \$a_style = NULL)
{
/* this way it works well only for orthogonal lines
imagesetthickness(\$image, \$thick);
return imageline(\$image, \$x1, \$y1, \$x2, \$y2, \$color);
*/

if (!is_null(\$a_style))
{
imagesetstyle(\$image, \$a_style);
}

if (\$thick == 1) {
return @imageline(\$image, \$x1, \$y1, \$x2, \$y2, (!is_null(\$a_style) ? IMG_COLOR_STYLED : \$color));
}
\$t = \$thick / 2 - 0.5;
if (\$x1 == \$x2 || \$y1 == \$y2) {
return imagefilledrectangle(\$image, round(min(\$x1, \$x2) - \$t), round(min(\$y1, \$y2) - \$t), round(max(\$x1, \$x2) + \$t), round(max(\$y1, \$y2) + \$t), (!is_null(\$a_style) ? IMG_COLOR_STYLED : \$color));
}

\$k = (\$y2 - \$y1) / (\$x2 - \$x1); //y = kx + q
\$a = \$t / sqrt(1 + pow(\$k, 2));
\$points = array(
round(\$x1 - (1+\$k)*\$a), round(\$y1 + (1-\$k)*\$a),
round(\$x1 - (1-\$k)*\$a), round(\$y1 - (1+\$k)*\$a),
round(\$x2 + (1+\$k)*\$a), round(\$y2 - (1-\$k)*\$a),
round(\$x2 + (1-\$k)*\$a), round(\$y2 + (1+\$k)*\$a),
);
return imagefilledpolygon(\$image, \$points, 4, (!is_null(\$a_style) ? IMG_COLOR_STYLED : \$color));
}

\$size = 100;
\$image = imagecreate(\$size, \$size);
\$black = imagecolorallocate(\$image, 0, 0, 0);
\$white = imagecolorallocate(\$image, 255, 255, 255);
\$a_style = array(\$white, \$white, \$white, \$white, \$white, \$black, \$black, \$black, \$black, \$black);

imagelinethick(\$image, 0, 0, \$size, \$size, \$white, 6, \$a_style);
imagepng(\$image);
imagedestroy(\$image);
?>
0

Senior Software DeveloperCommented:
But, having said that, the line dashes are NOT rotated with the line.
So, draw the line straight and then rotate it should work.

But playing with the array and the width produces some interesting results!!!!

\$a_style = array(\$white, \$white, \$white, \$white, \$white, \$black, \$black, \$black, \$black, \$black);
imagelinethick(\$image, 0, 0, \$size, \$size, \$white, 20, \$a_style);

Very odd!

0

Senior Software DeveloperCommented:
The other way (I think) is to construct a brush which is the right dash size you want and use that as the image, using IMG_COLOR_STYLEDBRUSHED rather than IMG_COLOR_STYLED
0

Author Commented:

Thanks for the fast reply, but I've got a small problem with that code you've just posted...

When I use this code, I get a rectangle with a dotted outline, rather than a dotted line 4 pixels thick...

\$image = imagecreate(48, 48);
\$gray = imagecolorallocate(\$image, 192, 192, 192);
\$black = imagecolorallocate(\$image, 0, 0, 0);
if (\$_GET['color'] != ''){
\$color = HexToRGB(\$_GET['color']);
} else {
\$color[0] = 255;
\$color[1] = 255;
\$color[2] = 255;
}
\$line = imagecolorallocate(\$image, \$color[0], \$color[1], \$color[2]);
if (\$_GET['style'] == 'dotted'){
\$a_style = array(
\$line,
\$line,
\$line
);
} elseif (\$_GET['style'] == 'solid'){
\$a_style = NULL;
}
imagelinethick(\$image, 5, 43, 43, 5, \$line, 4, \$a_style);
imageline(\$image, 0, 0, 0, 47, \$black);
imageline(\$image, 0, 0, 47, 0, \$black);
imageline(\$image, 47, 0, 47, 47, \$black);
imageline(\$image, 0, 47, 47, 47, \$black);
imagepng(\$image);
imagedestroy(\$image);

Is it a fault on my end?

Cheers!
0

Senior Software DeveloperCommented:
You can also use ...
imagerectangle(\$image, 0, 0, 47, 47, \$black);

imageline(\$image, 0, 0, 0, 47, \$black);
imageline(\$image, 0, 0, 47, 0, \$black);
imageline(\$image, 47, 0, 47, 47, \$black);
imageline(\$image, 0, 47, 47, 47, \$black);

0

Author Commented:
Ah, that works.

Cheers! :)
0