1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27: 28: 29: 30: 31: 32: 33:
34: class Mage_Catalog_Model_Product_Image extends Mage_Core_Model_Abstract
35: {
36: protected $_width;
37: protected $_height;
38: protected $_quality = 90;
39:
40: protected $_keepAspectRatio = true;
41: protected $_keepFrame = true;
42: protected $_keepTransparency = true;
43: protected $_constrainOnly = false;
44: protected $_backgroundColor = array(255, 255, 255);
45:
46: protected $_baseFile;
47: protected $_isBaseFilePlaceholder;
48: protected $_newFile;
49: protected $_processor;
50: protected $_destinationSubdir;
51: protected $_angle;
52:
53: protected $_watermarkFile;
54: protected $_watermarkPosition;
55: protected $_watermarkWidth;
56: protected $_watermarkHeigth;
57: protected $_watermarkImageOpacity = 70;
58:
59: 60: 61:
62: public function setWidth($width)
63: {
64: $this->_width = $width;
65: return $this;
66: }
67:
68: public function getWidth()
69: {
70: return $this->_width;
71: }
72:
73: 74: 75:
76: public function setHeight($height)
77: {
78: $this->_height = $height;
79: return $this;
80: }
81:
82: public function getHeight()
83: {
84: return $this->_height;
85: }
86:
87: 88: 89: 90: 91: 92:
93: public function setQuality($quality)
94: {
95: $this->_quality = $quality;
96: return $this;
97: }
98:
99: 100: 101: 102: 103:
104: public function getQuality()
105: {
106: return $this->_quality;
107: }
108:
109: 110: 111:
112: public function setKeepAspectRatio($keep)
113: {
114: $this->_keepAspectRatio = (bool)$keep;
115: return $this;
116: }
117:
118: 119: 120:
121: public function setKeepFrame($keep)
122: {
123: $this->_keepFrame = (bool)$keep;
124: return $this;
125: }
126:
127: 128: 129:
130: public function setKeepTransparency($keep)
131: {
132: $this->_keepTransparency = (bool)$keep;
133: return $this;
134: }
135:
136: 137: 138:
139: public function setConstrainOnly($flag)
140: {
141: $this->_constrainOnly = (bool)$flag;
142: return $this;
143: }
144:
145: 146: 147:
148: public function setBackgroundColor(array $rgbArray)
149: {
150: $this->_backgroundColor = $rgbArray;
151: return $this;
152: }
153:
154: 155: 156:
157: public function setSize($size)
158: {
159:
160: list($width, $height) = explode('x', strtolower($size), 2);
161: foreach (array('width', 'height') as $wh) {
162: $$wh = (int)$$wh;
163: if (empty($$wh))
164: $$wh = null;
165: }
166:
167:
168: $this->setWidth($width)->setHeight($height);
169:
170: return $this;
171: }
172:
173: protected function _checkMemory($file = null)
174: {
175:
176:
177:
178:
179: return $this->_getMemoryLimit() > ($this->_getMemoryUsage() + $this->_getNeedMemoryForFile($file)) || $this->_getMemoryLimit() == -1;
180: }
181:
182: protected function _getMemoryLimit()
183: {
184: $memoryLimit = trim(strtoupper(ini_get('memory_limit')));
185:
186: if (!isSet($memoryLimit[0])){
187: $memoryLimit = "128M";
188: }
189:
190: if (substr($memoryLimit, -1) == 'K') {
191: return substr($memoryLimit, 0, -1) * 1024;
192: }
193: if (substr($memoryLimit, -1) == 'M') {
194: return substr($memoryLimit, 0, -1) * 1024 * 1024;
195: }
196: if (substr($memoryLimit, -1) == 'G') {
197: return substr($memoryLimit, 0, -1) * 1024 * 1024 * 1024;
198: }
199: return $memoryLimit;
200: }
201:
202: protected function _getMemoryUsage()
203: {
204: if (function_exists('memory_get_usage')) {
205: return memory_get_usage();
206: }
207: return 0;
208: }
209:
210: protected function _getNeedMemoryForFile($file = null)
211: {
212: $file = is_null($file) ? $this->getBaseFile() : $file;
213: if (!$file) {
214: return 0;
215: }
216:
217: if (!file_exists($file) || !is_file($file)) {
218: return 0;
219: }
220:
221: $imageInfo = getimagesize($file);
222:
223: if (!isset($imageInfo[0]) || !isset($imageInfo[1])) {
224: return 0;
225: }
226: if (!isset($imageInfo['channels'])) {
227:
228: $imageInfo['channels'] = 4;
229: }
230: if (!isset($imageInfo['bits'])) {
231:
232: $imageInfo['bits'] = 8;
233: }
234: return round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65);
235: }
236:
237: 238: 239: 240: 241: 242:
243: protected function _rgbToString($rgbArray)
244: {
245: $result = array();
246: foreach ($rgbArray as $value) {
247: if (null === $value) {
248: $result[] = 'null';
249: }
250: else {
251: $result[] = sprintf('%02s', dechex($value));
252: }
253: }
254: return implode($result);
255: }
256:
257: 258: 259: 260: 261: 262:
263: public function setBaseFile($file)
264: {
265: $this->_isBaseFilePlaceholder = false;
266:
267: if (($file) && (0 !== strpos($file, '/', 0))) {
268: $file = '/' . $file;
269: }
270: $baseDir = Mage::getSingleton('catalog/product_media_config')->getBaseMediaPath();
271:
272: if ('/no_selection' == $file) {
273: $file = null;
274: }
275: if ($file) {
276: if ((!$this->_fileExists($baseDir . $file)) || !$this->_checkMemory($baseDir . $file)) {
277: $file = null;
278: }
279: }
280: if (!$file) {
281:
282: $isConfigPlaceholder = Mage::getStoreConfig("catalog/placeholder/{$this->getDestinationSubdir()}_placeholder");
283: $configPlaceholder = '/placeholder/' . $isConfigPlaceholder;
284: if ($isConfigPlaceholder && $this->_fileExists($baseDir . $configPlaceholder)) {
285: $file = $configPlaceholder;
286: }
287: else {
288:
289: $skinBaseDir = Mage::getDesign()->getSkinBaseDir();
290: $skinPlaceholder = "/images/catalog/product/placeholder/{$this->getDestinationSubdir()}.jpg";
291: $file = $skinPlaceholder;
292: if (file_exists($skinBaseDir . $file)) {
293: $baseDir = $skinBaseDir;
294: }
295: else {
296: $baseDir = Mage::getDesign()->getSkinBaseDir(array('_theme' => 'default'));
297: if (!file_exists($baseDir . $file)) {
298: $baseDir = Mage::getDesign()->getSkinBaseDir(array('_theme' => 'default', '_package' => 'base'));
299: }
300: }
301: }
302: $this->_isBaseFilePlaceholder = true;
303: }
304:
305: $baseFile = $baseDir . $file;
306:
307: if ((!$file) || (!file_exists($baseFile))) {
308: throw new Exception(Mage::helper('catalog')->__('Image file was not found.'));
309: }
310:
311: $this->_baseFile = $baseFile;
312:
313:
314: $path = array(
315: Mage::getSingleton('catalog/product_media_config')->getBaseMediaPath(),
316: 'cache',
317: Mage::app()->getStore()->getId(),
318: $path[] = $this->getDestinationSubdir()
319: );
320: if((!empty($this->_width)) || (!empty($this->_height)))
321: $path[] = "{$this->_width}x{$this->_height}";
322:
323:
324: $miscParams = array(
325: ($this->_keepAspectRatio ? '' : 'non') . 'proportional',
326: ($this->_keepFrame ? '' : 'no') . 'frame',
327: ($this->_keepTransparency ? '' : 'no') . 'transparency',
328: ($this->_constrainOnly ? 'do' : 'not') . 'constrainonly',
329: $this->_rgbToString($this->_backgroundColor),
330: 'angle' . $this->_angle,
331: 'quality' . $this->_quality
332: );
333:
334:
335: if ($this->getWatermarkFile()) {
336: $miscParams[] = $this->getWatermarkFile();
337: $miscParams[] = $this->getWatermarkImageOpacity();
338: $miscParams[] = $this->getWatermarkPosition();
339: $miscParams[] = $this->getWatermarkWidth();
340: $miscParams[] = $this->getWatermarkHeigth();
341: }
342:
343: $path[] = md5(implode('_', $miscParams));
344:
345:
346: $this->_newFile = implode('/', $path) . $file;
347:
348: return $this;
349: }
350:
351: public function getBaseFile()
352: {
353: return $this->_baseFile;
354: }
355:
356: public function getNewFile()
357: {
358: return $this->_newFile;
359: }
360:
361: 362: 363:
364: public function setImageProcessor($processor)
365: {
366: $this->_processor = $processor;
367: return $this;
368: }
369:
370: 371: 372:
373: public function getImageProcessor()
374: {
375: if( !$this->_processor ) {
376:
377:
378:
379:
380: $this->_processor = new Varien_Image($this->getBaseFile());
381: }
382: $this->_processor->keepAspectRatio($this->_keepAspectRatio);
383: $this->_processor->keepFrame($this->_keepFrame);
384: $this->_processor->keepTransparency($this->_keepTransparency);
385: $this->_processor->constrainOnly($this->_constrainOnly);
386: $this->_processor->backgroundColor($this->_backgroundColor);
387: $this->_processor->quality($this->_quality);
388: return $this->_processor;
389: }
390:
391: 392: 393: 394:
395: public function resize()
396: {
397: if (is_null($this->getWidth()) && is_null($this->getHeight())) {
398: return $this;
399: }
400: $this->getImageProcessor()->resize($this->_width, $this->_height);
401: return $this;
402: }
403:
404: 405: 406:
407: public function rotate($angle)
408: {
409: $angle = intval($angle);
410: $this->getImageProcessor()->rotate($angle);
411: return $this;
412: }
413:
414: 415: 416: 417: 418: 419: 420: 421:
422: public function setAngle($angle)
423: {
424: $this->_angle = $angle;
425: return $this;
426: }
427:
428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439:
440: public function setWatermark($file, $position=null, $size=null, $width=null, $heigth=null, $imageOpacity=null)
441: {
442: if ($this->_isBaseFilePlaceholder)
443: {
444: return $this;
445: }
446:
447: if ($file) {
448: $this->setWatermarkFile($file);
449: } else {
450: return $this;
451: }
452:
453: if ($position)
454: $this->setWatermarkPosition($position);
455: if ($size)
456: $this->setWatermarkSize($size);
457: if ($width)
458: $this->setWatermarkWidth($width);
459: if ($heigth)
460: $this->setWatermarkHeigth($heigth);
461: if ($imageOpacity)
462: $this->setImageOpacity($imageOpacity);
463:
464: $filePath = $this->_getWatermarkFilePath();
465:
466: if($filePath) {
467: $this->getImageProcessor()
468: ->setWatermarkPosition( $this->getWatermarkPosition() )
469: ->setWatermarkImageOpacity( $this->getWatermarkImageOpacity() )
470: ->setWatermarkWidth( $this->getWatermarkWidth() )
471: ->setWatermarkHeigth( $this->getWatermarkHeigth() )
472: ->watermark($filePath);
473: }
474:
475: return $this;
476: }
477:
478: 479: 480:
481: public function saveFile()
482: {
483: $filename = $this->getNewFile();
484: $this->getImageProcessor()->save($filename);
485: Mage::helper('core/file_storage_database')->saveFile($filename);
486: return $this;
487: }
488:
489: 490: 491:
492: public function getUrl()
493: {
494: $baseDir = Mage::getBaseDir('media');
495: $path = str_replace($baseDir . DS, "", $this->_newFile);
496: return Mage::getBaseUrl('media') . str_replace(DS, '/', $path);
497: }
498:
499: public function push()
500: {
501: $this->getImageProcessor()->display();
502: }
503:
504: 505: 506:
507: public function setDestinationSubdir($dir)
508: {
509: $this->_destinationSubdir = $dir;
510: return $this;
511: }
512:
513: 514: 515:
516: public function getDestinationSubdir()
517: {
518: return $this->_destinationSubdir;
519: }
520:
521: public function isCached()
522: {
523: return $this->_fileExists($this->_newFile);
524: }
525:
526: 527: 528: 529: 530: 531:
532: public function setWatermarkFile($file)
533: {
534: $this->_watermarkFile = $file;
535: return $this;
536: }
537:
538: 539: 540: 541: 542:
543: public function getWatermarkFile()
544: {
545: return $this->_watermarkFile;
546: }
547:
548: 549: 550: 551: 552: 553:
554: protected function _getWatermarkFilePath()
555: {
556: $filePath = false;
557:
558: if (!$file = $this->getWatermarkFile())
559: {
560: return $filePath;
561: }
562:
563: $baseDir = Mage::getSingleton('catalog/product_media_config')->getBaseMediaPath();
564:
565: if( $this->_fileExists($baseDir . '/watermark/stores/' . Mage::app()->getStore()->getId() . $file) ) {
566: $filePath = $baseDir . '/watermark/stores/' . Mage::app()->getStore()->getId() . $file;
567: } elseif ( $this->_fileExists($baseDir . '/watermark/websites/' . Mage::app()->getWebsite()->getId() . $file) ) {
568: $filePath = $baseDir . '/watermark/websites/' . Mage::app()->getWebsite()->getId() . $file;
569: } elseif ( $this->_fileExists($baseDir . '/watermark/default/' . $file) ) {
570: $filePath = $baseDir . '/watermark/default/' . $file;
571: } elseif ( $this->_fileExists($baseDir . '/watermark/' . $file) ) {
572: $filePath = $baseDir . '/watermark/' . $file;
573: } else {
574: $baseDir = Mage::getDesign()->getSkinBaseDir();
575: if( $this->_fileExists($baseDir . $file) ) {
576: $filePath = $baseDir . $file;
577: }
578: }
579:
580: return $filePath;
581: }
582:
583: 584: 585: 586: 587: 588:
589: public function setWatermarkPosition($position)
590: {
591: $this->_watermarkPosition = $position;
592: return $this;
593: }
594:
595: 596: 597: 598: 599:
600: public function getWatermarkPosition()
601: {
602: return $this->_watermarkPosition;
603: }
604:
605: 606: 607: 608: 609: 610:
611: public function setWatermarkImageOpacity($imageOpacity)
612: {
613: $this->_watermarkImageOpacity = $imageOpacity;
614: return $this;
615: }
616:
617: 618: 619: 620: 621:
622: public function getWatermarkImageOpacity()
623: {
624: return $this->_watermarkImageOpacity;
625: }
626:
627: 628: 629: 630: 631: 632:
633: public function setWatermarkSize($size)
634: {
635: if( is_array($size) ) {
636: $this->setWatermarkWidth($size['width'])
637: ->setWatermarkHeigth($size['heigth']);
638: }
639: return $this;
640: }
641:
642: 643: 644: 645: 646: 647:
648: public function setWatermarkWidth($width)
649: {
650: $this->_watermarkWidth = $width;
651: return $this;
652: }
653:
654: 655: 656: 657: 658:
659: public function getWatermarkWidth()
660: {
661: return $this->_watermarkWidth;
662: }
663:
664: 665: 666: 667: 668: 669:
670: public function setWatermarkHeigth($heigth)
671: {
672: $this->_watermarkHeigth = $heigth;
673: return $this;
674: }
675:
676: 677: 678: 679: 680:
681: public function getWatermarkHeigth()
682: {
683: return $this->_watermarkHeigth;
684: }
685:
686: public function clearCache()
687: {
688: $directory = Mage::getBaseDir('media') . DS.'catalog'.DS.'product'.DS.'cache'.DS;
689: $io = new Varien_Io_File();
690: $io->rmdir($directory, true);
691:
692: Mage::helper('core/file_storage_database')->deleteFolder($directory);
693: }
694:
695: 696: 697: 698: 699: 700: 701:
702: protected function _fileExists($filename) {
703: if (file_exists($filename)) {
704: return true;
705: } else {
706: return Mage::helper('core/file_storage_database')->saveFileToFilesystem($filename);
707: }
708: }
709: }
710: