Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trim filter #586

Closed
igormukhingmailcom opened this issue Apr 2, 2015 · 6 comments
Closed

Trim filter #586

igormukhingmailcom opened this issue Apr 2, 2015 · 6 comments

Comments

@igormukhingmailcom
Copy link

Hi.

Will be nice if trim filter will be implemented to remove white (or whatever) edges.
http://php.net/manual/en/imagick.trimimage.php

@makasim
Copy link
Collaborator

makasim commented Apr 2, 2015

I think it is better to open this issue https://github.com/avalanche123/Imagine here first. Or maybe it is implemented there.

@igormukhingmailcom
Copy link
Author

You're right, @makasim

@igormukhingmailcom
Copy link
Author

@makasim WDYT?
I can make PR if you're interested to have that available from the box.
Now all decorated for using as extension in some AppBundle.

# app/config.yml
parameters:
    liip_imagine.trim.fuzz: 20

liip_imagine:
    # Use imagick driver for built-in (and faster) trim
    # driver: imagick
    filter_sets:
        hires:
            ...
            filters:
                trim:
                  fuzz: %liip_imagine.trim.fuzz%
# services.yml
services:
    liip_imagine.filter.loader.trim:
        class: AppBundle\Imagine\Filter\Loader\TrimFilterLoader
        tags :
            - { name: liip_imagine.filter.loader, loader: trim }
<?php

namespace AppBundle\Imagine\Filter\Loader;

use Liip\ImagineBundle\Imagine\Filter\Loader\LoaderInterface;
use Imagine\Image\ImageInterface;

use AppBundle\Imagine\Filter\Basic\Trim;

/**
 * @author Igor Mukhin <[email protected]>
 */
class TrimFilterLoader implements LoaderInterface
{
    /**
     * {@inheritDoc}
     */
    public function load(ImageInterface $image, array $options = array())
    {
        if (!empty($options['fuzz'])) {
            $fuzz = $options['fuzz'];
        }

        $filter = new Trim($fuzz);
        return $filter->apply($image);
    }
}
<?php

namespace AppBundle\Imagine\Filter\Basic;

use Imagine\Filter\FilterInterface;
use Imagine\Image\ImageInterface;
use Imagine\Image\Palette\Color\ColorInterface;
use Imagine\Image\Box;
use Imagine\Image\Point;

use Imagine\Imagick\Image as ImagickImage;

/**
 * A trim filter
 *
 * @see http://zavaboy.com/2007/10/06/trim_an_image_using_php_and_gd
 * @author Igor Mukhin <[email protected]>
 */
class Trim implements FilterInterface
{
    private $fuzz;

    /**
     * @param integer $fuzz How much tolerance is acceptable to consider two colors as the same
     */
    public function __construct($fuzz = 0)
    {
        $this->fuzz = $fuzz;
    }

    /**
     * {@inheritdoc}
     */
    public function apply(ImageInterface $image)
    {
        if ($image instanceof ImagickImage) {
            $imagick = $image->getImagick();
            $range = $imagick->getQuantumRange();
            $imagick->trimImage($this->fuzz / 100 * $range['quantumRangeLong']);

            return $image;
        }

        $size = $image->getSize();
        $origWidth = $size->getWidth();
        $origHeight = $size->getHeight();

        $xMin = $origWidth;
        $xMax = 0;

        // Scanning for the edges
        for ($iy = 0; $iy < $origHeight; $iy++) {
            $first = true;
            for ($ix = 0; $ix < $origWidth; $ix++) {
                $checkColor = $image->getColorAt(new Point($ix, $iy));

                // Take color of top-left corner as background
                if ($iy == 0 && $ix == 0) {
                    $background = $checkColor;
                }

                if (!$this->isSimilar($background, $checkColor)) {
                    if ($xMin > $ix) {
                        $xMin = $ix;
                    }

                    if ($xMax < $ix) {
                        $xMax = $ix;
                    }

                    if (!isset($yMin)) {
                        $yMin = $iy;
                    }

                    $yMax = $iy;

                    if ($first) {
                        $ix = $xMax;
                        $first = false;
                    }
                }
            }
        }

        if (!isset($yMin)) {
            $yMin = 1;
        }

        if (!isset($yMax)) {
            $yMax = $origHeight;
        }

        // The new width and height of the image. (not including padding)
        $croppedWidth = 1+$xMax-$xMin;
        $croppedHeight = 1+$yMax-$yMin;

        $start = new Point($xMin, $yMin);
        $size = new Box($croppedWidth, $croppedHeight);

        return $image->crop($start, $size);
    }

    /**
     * @param  ColorInterface $color1
     * @param  ColorInterface $color2
     * @return boolean
     */
    private function isSimilar(ColorInterface $color1, ColorInterface $color2) {

        $components = array(
            ColorInterface::COLOR_RED,
            ColorInterface::COLOR_GREEN,
            ColorInterface::COLOR_BLUE
        );

        foreach ($components as $component) {
            if (abs($color1->getValue($component) - $color2->getValue($component)) > $this->fuzz) return false;
        }

        return true;
    }
}

@makasim
Copy link
Collaborator

makasim commented Apr 3, 2015

The trim filter may go to the Imagine library (if it is not too application specific) where the the loader can be merged to the bundle.

I'd vote 👍 to add it.

@AlmogBaku
Copy link

Any update about this feature?

@michellesanver
Copy link
Contributor

I am going through all issues to sort and prioritise. Is this still an issue you want an update on @AlmogBaku? Since this is so old, please open a new issue if that is the case with your needs and wishes, and we will prioritise accordingly. Thanks a lot! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants