1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette;
13:
14: use Nette;
15:
16:
17:
18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
30: class ImageMagick extends Image
31: {
32:
33: public static $path = '';
34:
35:
36: public static $tempDir;
37:
38:
39: private $file;
40:
41:
42: private $isTemporary = FALSE;
43:
44:
45: private $width;
46:
47:
48: private $height;
49:
50:
51:
52: 53: 54: 55: 56:
57: public function __construct($file, & $format = NULL)
58: {
59: if (!is_file($file)) {
60: throw new \InvalidArgumentException("File '$file' not found.");
61: }
62: $format = $this->setFile(realpath($file));
63: if ($format === 'JPEG') $format = self::JPEG;
64: elseif ($format === 'PNG') $format = self::PNG;
65: elseif ($format === 'GIF') $format = self::GIF;
66: }
67:
68:
69:
70: 71: 72: 73:
74: public function getWidth()
75: {
76: return $this->file === NULL ? parent::getWidth() : $this->width;
77: }
78:
79:
80:
81: 82: 83: 84:
85: public function getHeight()
86: {
87: return $this->file === NULL ? parent::getHeight() : $this->height;
88: }
89:
90:
91:
92: 93: 94: 95:
96: public function getImageResource()
97: {
98: if ($this->file !== NULL) {
99: if (!$this->isTemporary) {
100: $this->execute("convert -strip %input %output", self::PNG);
101: }
102: $this->setImageResource(imagecreatefrompng($this->file));
103: if ($this->isTemporary) {
104: unlink($this->file);
105: }
106: $this->file = NULL;
107: }
108:
109: return parent::getImageResource();
110: }
111:
112:
113:
114: 115: 116: 117: 118: 119: 120:
121: public function resize($width, $height, $flags = self::FIT)
122: {
123: if ($this->file === NULL) {
124: return parent::resize($width, $height, $flags);
125: }
126:
127: $mirror = '';
128: if ($width < 0) $mirror .= ' -flop';
129: if ($height < 0) $mirror .= ' -flip';
130: list($newWidth, $newHeight) = self::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $flags);
131: $this->execute("convert -resize {$newWidth}x{$newHeight}! {$mirror} -strip %input %output", self::PNG);
132: return $this;
133: }
134:
135:
136:
137: 138: 139: 140: 141: 142: 143: 144:
145: public function crop($left, $top, $width, $height)
146: {
147: if ($this->file === NULL) {
148: return parent::crop($left, $top, $width, $height);
149: }
150:
151: $left = max(0, (int) $left);
152: $top = max(0, (int) $top);
153: $width = min((int) $width, $this->getWidth() - $left);
154: $height = min((int) $height, $this->getHeight() - $top);
155: $this->execute("convert -crop {$width}x{$height}+{$left}+{$top} -strip %input %output", self::PNG);
156: return $this;
157: }
158:
159:
160:
161: 162: 163: 164: 165: 166: 167:
168: public function save($file = NULL, $quality = NULL, $type = NULL)
169: {
170: if ($this->file === NULL) {
171: return parent::save($file, $quality, $type);
172: }
173:
174: $quality = $quality === NULL ? '' : '-quality ' . max(0, min(100, (int) $quality));
175: if ($file === NULL) {
176: $this->execute("convert $quality -strip %input %output", $type === NULL ? self::PNG : $type);
177: readfile($this->file);
178:
179: } else {
180: $this->execute("convert $quality -strip %input %output", (string) $file);
181: }
182: return TRUE;
183: }
184:
185:
186:
187: 188: 189: 190: 191:
192: private function setFile($file)
193: {
194: $this->file = $file;
195: $res = $this->execute('identify -format "%w,%h,%m" ' . escapeshellarg($this->file));
196: if (!$res) {
197: throw new \Exception("Unknown image type in file '$file' or ImageMagick not available.");
198: }
199: list($this->width, $this->height, $format) = explode(',', $res, 3);
200: return $format;
201: }
202:
203:
204:
205: 206: 207: 208: 209: 210:
211: private function execute($command, $output = NULL)
212: {
213: $command = str_replace('%input', escapeshellarg($this->file), $command);
214: if ($output) {
215: $newFile = is_string($output)
216: ? $output
217: : (self::$tempDir ? self::$tempDir : dirname($this->file)) . '/' . uniqid('_tempimage', TRUE) . image_type_to_extension($output);
218: $command = str_replace('%output', escapeshellarg($newFile), $command);
219: }
220:
221: $lines = array();
222: exec(self::$path . $command, $lines, $status); 223:
224: if ($output) {
225: if ($status != 0) {
226: throw new \Exception("Unknown error while calling ImageMagick.");
227: }
228: if ($this->isTemporary) {
229: unlink($this->file);
230: }
231: $this->setFile($newFile);
232: $this->isTemporary = !is_string($output);
233: }
234:
235: return $lines ? $lines[0] : FALSE;
236: }
237:
238:
239:
240: 241: 242: 243:
244: public function __destruct()
245: {
246: if ($this->file !== NULL && $this->isTemporary) {
247: unlink($this->file);
248: }
249: }
250:
251: }