Solved

modifying a line function to support dotted lines

Posted on 2006-07-14
8
513 Views
Last Modified: 2013-12-12
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);
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
?>


Cheers guys!
0
Comment
Question by:Cyber-Drugs
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 2
8 Comments
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17107734
<?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);
header('Content-Type: image/png');
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
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17107740
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);
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
?>
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17107772
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17107791
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
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 17107859
Hi RQuadling,

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);
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);


Is it a fault on my end?

Cheers!
0
 
LVL 40

Accepted Solution

by:
Richard Quadling earned 500 total points
ID: 17107946
<?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);
header('Content-Type: image/png');
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);
header('Content-Type: image/png');
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
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17107964
You can also use ...
imagerectangle($image, 0, 0, 47, 47, $black);

instead of ...

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
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 17107983
Ah, that works.

Cheers! :)
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article discusses four methods for overlaying images in a container on a web page
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

738 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question