Intervention / image

PHP Image Processing
https://image.intervention.io
MIT License
13.84k stars 1.5k forks source link

imagesetthickness() in DrawLineModifier has no effect in certain environments #1298

Closed ulfie22 closed 6 months ago

ulfie22 commented 7 months ago

Describe the bug The width parameter for the drawLine method was implemented in v 3.3.3. It worked correctly upon upgrade. For reasons unknown, it has stopped working and all drawn lines are 1 px, no matter what the width parameter is. This is so effing weird!

Code Example

public function drawLine($fromX, $fromY, $toX, $toY, $color, $width): void
    {
        ray($width)->blue();
        $this->image->drawLine(function ($line) use ($fromX, $fromY, $toX, $toY, $color, $width) {
            $line->from($fromX, $fromY);      // starting point of line
            $line->to($toX, $toY);            // ending point
            $line->color($color);             // color of line
            $line->width($width);             // line width in pixels
        });
    }

Expected behavior In the above example, $width was set to 4 (and verified by ray()) - image produced has a 1 px line

Images CleanShot 2024-02-07 at 18 33 25@2x

Environment (please complete the following information):

olivervogel commented 7 months ago

That's really strange. Unfortunately, I can't reproduce it right now.

According to a very old comment in the PHP documentation, the function imagesetthickness() does not work if imageantialias() is activated. I can't say whether this is still relevant (my tests show that it works with both options). But maybe you can comment out the antialias line in the vendor code and see if it has an influence.

ulfie22 commented 7 months ago

@olivervogel Thanks for this response. THAT ACTUALLY FIXES THE PROBLEM! Is there a way for me to override this one function? I tried to just override that one class, but it's buried so deep inside Image Intervention that my override was not being recognized. Thank you for your help!

ulfie22 commented 7 months ago

@olivervogel Thanks for this response. THAT ACTUALLY FIXES THE PROBLEM! Is there a way for me to override this one function? I tried to just override that one class, but it's buried so deep inside Image Intervention that my override was not being recognized. Thank you for your help!

olivervogel commented 7 months ago

On the one hand, this is good news. On the other hand, it is also bad news, as the current implementation does not seem to work on certain systems. What particularly surprises me is that I can't detect any problems and I'm even using the same setup (MacOS, PHP 8.3.2, GD). And it is not really clear what triggers the behavior and how to handle this.

As a quick solution for the moment, I would suggest to use a custom modifier that replicates the function of the DrawLineModifer without antialiasing.

It could look like this:

use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Interfaces\ImageInterface;

class DrawPixelLine implements ModifierInterface
{
    public function __construct(
        protected int $fromX,
        protected int $fromY,
        protected int $toX,
        protected int $toY,
        protected mixed $color,
        protected int $width
    ) {
    }

    public function apply(ImageInterface $image): ImageInterface
    {
        $lineColor = $image->driver()->colorProcessor($image->colorspace())->colorToNative(
            $image->driver()->handleInput($this->color)
        );

        foreach ($image as $frame) {
            imagealphablending($frame->native(), true);
            imagesetthickness($frame->native(), $this->width);
            imageline(
                $frame->native(),
                $this->fromX,
                $this->fromY,
                $this->toX,
                $this->toY,
                $lineColor
            );
        }

        return $image;
    }
}

// apply modifier
$image->modify(new DrawPixelLine(10, 20, 130, 200, 'ff00ff', 3));

I'm sorry that I can't offer you a better solution at the moment.

olivervogel commented 7 months ago

Here are the specs of my local GD installation for comparison. Maybe there are differences that you can recognize.

Bildschirmfoto 2024-02-09 um 14 56 05
ulfie22 commented 6 months ago

@olivervogel wow - thank you for all the great information. After some further research on my end, I am pretty sure this has something to do with my system, not your code. One of my co-workers pulled my code to his machine (actually a windows box running Sail) and everything worked as expected. I've been trying to get Laravel Herd to work successfully so my guess is something in that process caused this issue. I'm going to say thank you (big time!) and close this - I don't think you need to spend any more time on it unless someone else encounters the same thing.