xref: /dokuwiki/vendor/splitbrain/slika/src/ImageMagickAdapter.php (revision 6a8e48eda246f872402bf5b85763f276cd4c319d)
1<?php
2
3
4namespace splitbrain\slika;
5
6/**
7 * Image Processing Adapter for ImageMagick's command line utility `convert`
8 */
9class ImageMagickAdapter extends Adapter
10{
11    /** @var array the CLI arguments to run imagemagick */
12    protected $args = [];
13
14    /** @inheritDoc */
15    public function __construct($imagepath, $options = [])
16    {
17        parent::__construct($imagepath, $options);
18
19        if (!is_executable($this->options['imconvert'])) {
20            throw new Exception('Can not find or run ' . $this->options['imconvert']);
21        }
22
23        $this->args[] = $this->options['imconvert'];
24        $this->args[] = $imagepath;
25    }
26
27    /** @inheritDoc */
28    public function autorotate()
29    {
30        $this->args[] = '-auto-orient';
31        return $this;
32    }
33
34    /** @inheritDoc */
35    public function rotate($orientation)
36    {
37        $orientation = (int)$orientation;
38        if ($orientation < 0 || $orientation > 8) {
39            throw new Exception('Unknown rotation given');
40        }
41
42        // rotate
43        $this->args[] = '-rotate';
44        if (in_array($orientation, [3, 4])) {
45            $this->args[] = '180';
46        } elseif (in_array($orientation, [5, 6])) {
47            $this->args[] = '90';
48        } elseif (in_array($orientation, [7, 8])) {
49            $this->args[] = '270';
50        }
51
52        // additionally flip
53        if (in_array($orientation, [2, 5, 7, 4])) {
54            $this->args[] = '-flop';
55        }
56        return $this;
57    }
58
59    /**
60     * @inheritDoc
61     * @throws Exception
62     */
63    public function resize($width, $height, $upscale = true)
64    {
65        if ($width == 0 && $height == 0) {
66            throw new Exception('You can not resize to 0x0');
67        }
68        if ($width == 0) $width = '';
69        if ($height == 0) $height = '';
70
71        $size = $width . 'x' . $height;
72        if (!$upscale) $size .= '>';
73
74        $this->args[] = '-resize';
75        $this->args[] = $size;
76        return $this;
77    }
78
79    /**
80     * @inheritDoc
81     * @throws Exception
82     */
83    public function crop($width, $height, $upscale = true)
84    {
85        $width = (int)$width;
86        $height = (int)$height;
87        if ($width == 0 && $height == 0) {
88            throw new Exception('You can not crop to 0x0');
89        }
90
91        if ($width == 0) $width = $height;
92        if ($height == 0) $height = $width;
93
94        $size = $width . 'x' . $height;
95
96        $this->args[] = '-resize';
97        $this->args[] = $upscale ? "$size^" : "$size^>";
98        $this->args[] = '-gravity';
99        $this->args[] = 'center';
100        $this->args[] = '-crop';
101        $this->args[] = "$size+0+0";
102        $this->args[] = '+repage';
103        return $this;
104    }
105
106    /**
107     * @inheritDoc
108     * @throws Exception
109     */
110    public function save($path, $extension = '')
111    {
112        if ($extension === 'jpg') {
113            $extension = 'jpeg';
114        }
115
116        $this->args[] = '-quality';
117        $this->args[] = $this->options['quality'];
118
119        if ($extension !== '') $path = $extension . ':' . $path;
120        $this->args[] = $path;
121
122        $args = array_map('escapeshellarg', $this->args);
123
124        $cmd = join(' ', $args);
125        $output = [];
126        $return = 0;
127        exec($cmd, $output, $return);
128
129        if ($return !== 0) {
130            throw new Exception('ImageMagick returned non-zero exit code for ' . $cmd);
131        }
132    }
133}
134