Gregwar / Image

A PHP library to handle images
MIT License
1k stars 190 forks source link

Discussion: merge (feature/function) not work as expected #112

Open Bogdaan opened 8 years ago

Bogdaan commented 8 years ago

I have some issues with merge method after image resize (scale resize). For example: If you images is too large 2000x1000 and you need preserve aspect ratio - then you resize images with scaleResize. Typycal task for merge: place watermark over image.

But you can not use both methods together:

Case A) reseze + merge:

        echo $srcImg
            ->scaleResize($width, $height)
            ->merge($watermarkImg,
                $srcWidth - $watermarkW,
                $srcHeight - $watermarkH
            )
            ->html();

Result: watermark on transparent background (INVISIBLE) depends on aspect ratio.

Case B) merge + resize:

        echo $srcImg
            ->merge($watermarkImg,
                $srcWidth - $watermarkW,
                $srcHeight - $watermarkH
            )
            ->scaleResize($width, $height)
            ->html();

Result: watermark is visible but too small (resized with image).

My solution (compare ratio before place):

        // need this sizes
        $width = 1000;
        $height = 300;

        $watermarkPath = /tmp/watermark.png';
        $watermarkImg = AppImage::open($watermarkPath);

        $watermarkW = 157;
        $watermarkH = 50;

        $srcImg = AppImage::open('/tmp/test.jpg');

        $srcWidth = $srcImg->width();
        $srcHeight = $srcImg->height();

        $aspectRatio = $srcWidth / $srcHeight;
        $needRatio = $width / $height;

        $resultXOffset = $width - $watermarkW;
        $resultYOffset = $height - $watermarkH;

        if ($needRatio < $aspectRatio) {
            $realHeight = $width / $aspectRatio;
            $resultYOffset = $realHeight - $watermarkH + ($height - $realHeight) / 2;

        } else if ($needRatio > $aspectRatio) {
            $realWidth = $height * $aspectRatio;
            $resultXOffset = $realWidth - $watermarkW + ($width - $realWidth) / 2;
        }

        echo $srcImg
            ->scaleResize($width, $height)
            ->merge($watermarkImg, $resultXOffset, $resultYOffset)
            ->html();

So, now it is impossible place watermark on top/left/bottom of images?

Gregwar commented 8 years ago

I guess your problem is to get the image width and height after resize after all, right?

Bogdaan commented 8 years ago

@Gregwar yes resize works as expected, but after resize merge place image on empty place (not image).

aspectRatio ( > 1 )

-------------
|   empty   |
|   image   |
|   empty   |
-------------

or aspectRatio ( < 1 )

---------------------------
|   empty  image empty    |
---------------------------
Bogdaan commented 8 years ago

For example other library have a method

Intervention\Image\Image insert(mixed $source, [string $position, [integer $x, integer $y]])

with position parameter:

And works as expected. May be similar method would be useful?

Gregwar commented 8 years ago

This is indeed a good idea to add this If you do a PR i'll review it