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: list($left, $top, $width, $height) = self::calculateCutout($this->getWidth(), $this->getHeight(), $left, $top, $width, $height);
152: $this->execute("convert -crop {$width}x{$height}+{$left}+{$top} -strip %input %output", self::PNG);
153: return $this;
154: }
155:
156:
157:
158: 159: 160: 161: 162: 163: 164:
165: public function save($file = NULL, $quality = NULL, $type = NULL)
166: {
167: if ($this->file === NULL) {
168: return parent::save($file, $quality, $type);
169: }
170:
171: $quality = $quality === NULL ? '' : '-quality ' . max(0, min(100, (int) $quality));
172: if ($file === NULL) {
173: $this->execute("convert $quality -strip %input %output", $type === NULL ? self::PNG : $type);
174: readfile($this->file);
175:
176: } else {
177: $this->execute("convert $quality -strip %input %output", (string) $file);
178: }
179: return TRUE;
180: }
181:
182:
183:
184: 185: 186: 187: 188:
189: private function setFile($file)
190: {
191: $this->file = $file;
192: $res = $this->execute('identify -format "%w,%h,%m" ' . escapeshellarg($this->file));
193: if (!$res) {
194: throw new \Exception("Unknown image type in file '$file' or ImageMagick not available.");
195: }
196: list($this->width, $this->height, $format) = explode(',', $res, 3);
197: return $format;
198: }
199:
200:
201:
202: 203: 204: 205: 206: 207:
208: private function execute($command, $output = NULL)
209: {
210: $command = str_replace('%input', escapeshellarg($this->file), $command);
211: if ($output) {
212: $newFile = is_string($output)
213: ? $output
214: : (self::$tempDir ? self::$tempDir : dirname($this->file)) . '/' . uniqid('_tempimage', TRUE) . image_type_to_extension($output);
215: $command = str_replace('%output', escapeshellarg($newFile), $command);
216: }
217:
218: $lines = array();
219: exec(self::$path . $command, $lines, $status);
220:
221: if ($output) {
222: if ($status != 0) {
223: throw new \Exception("Unknown error while calling ImageMagick.");
224: }
225: if ($this->isTemporary) {
226: unlink($this->file);
227: }
228: $this->setFile($newFile);
229: $this->isTemporary = !is_string($output);
230: }
231:
232: return $lines ? $lines[0] : FALSE;
233: }
234:
235:
236:
237: 238: 239: 240:
241: public function __destruct()
242: {
243: if ($this->file !== NULL && $this->isTemporary) {
244: unlink($this->file);
245: }
246: }
247:
248: }
249: