1<?php
2
3namespace Intervention\Image\Gd\Commands;
4
5use Intervention\Image\Gd\Color;
6
7class TrimCommand extends ResizeCommand
8{
9    /**
10     * Trims away parts of an image
11     *
12     * @param  \Intervention\Image\Image $image
13     * @return boolean
14     */
15    public function execute($image)
16    {
17        $base = $this->argument(0)->type('string')->value();
18        $away = $this->argument(1)->value();
19        $tolerance = $this->argument(2)->type('numeric')->value(0);
20        $feather = $this->argument(3)->type('numeric')->value(0);
21
22        $width = $image->getWidth();
23        $height = $image->getHeight();
24
25        // default values
26        $checkTransparency = false;
27
28        // define borders to trim away
29        if (is_null($away)) {
30            $away = ['top', 'right', 'bottom', 'left'];
31        } elseif (is_string($away)) {
32            $away = [$away];
33        }
34
35        // lower border names
36        foreach ($away as $key => $value) {
37            $away[$key] = strtolower($value);
38        }
39
40        // define base color position
41        switch (strtolower($base)) {
42            case 'transparent':
43            case 'trans':
44                $checkTransparency = true;
45                $base_x = 0;
46                $base_y = 0;
47                break;
48
49            case 'bottom-right':
50            case 'right-bottom':
51                $base_x = $width - 1;
52                $base_y = $height - 1;
53                break;
54
55            default:
56            case 'top-left':
57            case 'left-top':
58                $base_x = 0;
59                $base_y = 0;
60                break;
61        }
62
63        // pick base color
64        if ($checkTransparency) {
65            $color = new Color; // color will only be used to compare alpha channel
66        } else {
67            $color = $image->pickColor($base_x, $base_y, 'object');
68        }
69
70        $top_x = 0;
71        $top_y = 0;
72        $bottom_x = $width;
73        $bottom_y = $height;
74
75        // search upper part of image for colors to trim away
76        if (in_array('top', $away)) {
77
78            for ($y=0; $y < ceil($height/2); $y++) {
79                for ($x=0; $x < $width; $x++) {
80
81                    $checkColor = $image->pickColor($x, $y, 'object');
82
83                    if ($checkTransparency) {
84                        $checkColor->r = $color->r;
85                        $checkColor->g = $color->g;
86                        $checkColor->b = $color->b;
87                    }
88
89                    if ($color->differs($checkColor, $tolerance)) {
90                        $top_y = max(0, $y - $feather);
91                        break 2;
92                    }
93
94                }
95            }
96
97        }
98
99        // search left part of image for colors to trim away
100        if (in_array('left', $away)) {
101
102            for ($x=0; $x < ceil($width/2); $x++) {
103                for ($y=$top_y; $y < $height; $y++) {
104
105                    $checkColor = $image->pickColor($x, $y, 'object');
106
107                    if ($checkTransparency) {
108                        $checkColor->r = $color->r;
109                        $checkColor->g = $color->g;
110                        $checkColor->b = $color->b;
111                    }
112
113                    if ($color->differs($checkColor, $tolerance)) {
114                        $top_x = max(0, $x - $feather);
115                        break 2;
116                    }
117
118                }
119            }
120
121        }
122
123        // search lower part of image for colors to trim away
124        if (in_array('bottom', $away)) {
125
126            for ($y=($height-1); $y >= floor($height/2)-1; $y--) {
127                for ($x=$top_x; $x < $width; $x++) {
128
129                    $checkColor = $image->pickColor($x, $y, 'object');
130
131                    if ($checkTransparency) {
132                        $checkColor->r = $color->r;
133                        $checkColor->g = $color->g;
134                        $checkColor->b = $color->b;
135                    }
136
137                    if ($color->differs($checkColor, $tolerance)) {
138                        $bottom_y = min($height, $y+1 + $feather);
139                        break 2;
140                    }
141
142                }
143            }
144
145        }
146
147        // search right part of image for colors to trim away
148        if (in_array('right', $away)) {
149
150            for ($x=($width-1); $x >= floor($width/2)-1; $x--) {
151                for ($y=$top_y; $y < $bottom_y; $y++) {
152
153                    $checkColor = $image->pickColor($x, $y, 'object');
154
155                    if ($checkTransparency) {
156                        $checkColor->r = $color->r;
157                        $checkColor->g = $color->g;
158                        $checkColor->b = $color->b;
159                    }
160
161                    if ($color->differs($checkColor, $tolerance)) {
162                        $bottom_x = min($width, $x+1 + $feather);
163                        break 2;
164                    }
165
166                }
167            }
168
169        }
170
171
172        // trim parts of image
173        return $this->modify($image, 0, 0, $top_x, $top_y, ($bottom_x-$top_x), ($bottom_y-$top_y), ($bottom_x-$top_x), ($bottom_y-$top_y));
174
175    }
176}
177