1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: class Ansel_Image Implements Iterator
15: {
16: 17: 18: 19: 20:
21: public $gallery;
22:
23: 24: 25: 26: 27:
28: public $id = null;
29:
30: 31: 32: 33: 34:
35: public $filename = 'Untitled';
36:
37: 38: 39: 40: 41:
42: public $caption = '';
43:
44: 45: 46: 47: 48:
49: public $type = 'image/jpeg';
50:
51: 52: 53: 54: 55:
56: public $uploaded;
57:
58: 59: 60: 61: 62:
63: public $sort;
64:
65: 66: 67: 68: 69:
70: public ;
71:
72: 73: 74: 75:
76: public $facesCount;
77:
78: 79: 80: 81: 82:
83: public $lat;
84:
85: 86: 87: 88: 89:
90: public $lng;
91:
92: 93: 94: 95: 96:
97: public $location;
98:
99: 100: 101: 102: 103:
104: public $geotag_timestamp;
105:
106: 107: 108: 109: 110:
111: public $originalDate;
112:
113: 114: 115: 116: 117:
118: protected $_image;
119:
120: 121: 122: 123: 124:
125: protected $_dirty;
126:
127: 128: 129: 130: 131:
132: protected $_loaded = array();
133:
134: 135: 136: 137: 138:
139: protected $_data = array();
140: 141: 142: 143: 144:
145: protected $_tags = array();
146:
147: 148: 149: 150: 151:
152: protected $_exif = array();
153:
154: 155: 156: 157: 158: 159: 160:
161: public function __construct(array $image = array())
162: {
163: if ($image) {
164: $this->filename = $image['image_filename'];
165:
166: if (!empty($image['gallery_id'])) {
167: $this->gallery = $image['gallery_id'];
168: }
169: if (!empty($image['image_caption'])) {
170: $this->caption = $image['image_caption'];
171: }
172: if (isset($image['image_sort'])) {
173: $this->sort = $image['image_sort'];
174: }
175: if (!empty($image['image_id'])) {
176: $this->id = $image['image_id'];
177: }
178: if (!empty($image['data'])) {
179: $this->_data['full'] = $image['data'];
180: }
181: if (!empty($image['image_uploaded_date'])) {
182: $this->uploaded = $image['image_uploaded_date'];
183: } else {
184: $this->uploaded = time();
185: }
186: if (!empty($image['image_type'])) {
187: $this->type = $image['image_type'];
188: }
189: if (!empty($image['tags'])) {
190: $this->_tags = $image['tags'];
191: }
192: if (!empty($image['image_faces'])) {
193: $this->facesCount = $image['image_faces'];
194: }
195:
196: $this->location = !empty($image['image_location']) ? $image['image_location'] : '';
197:
198:
199:
200:
201: if (!empty($image['image_original_date'])) {
202: $this->originalDate = $image['image_original_date'];
203: } else {
204: $this->originalDate = $this->uploaded;
205: }
206: $this->lat = !empty($image['image_latitude']) ? $image['image_latitude'] : '';
207: $this->lng = !empty($image['image_longitude']) ? $image['image_longitude'] : '';
208: $this->geotag_timestamp = !empty($image['image_geotag_date']) ? $image['image_geotag_date'] : '0';
209: }
210:
211: $this->_image = Ansel::getImageObject();
212: $this->_image->reset();
213: $this->id = !empty($image['image_id']) ? $image['image_id'] : null;
214: }
215:
216: 217: 218: 219: 220:
221: public function &getHordeImage()
222: {
223: return $this->_image;
224: }
225:
226: 227: 228: 229: 230: 231: 232: 233:
234: public function getVFSPath($view = 'full', Ansel_Style $style = null)
235: {
236: return $this->getVFSPathFromHash($this->getViewHash($view, $style));
237: }
238:
239: 240: 241: 242: 243: 244: 245:
246: public function getVFSPathFromHash($hash)
247: {
248: return '.horde/ansel/'
249: . substr(str_pad($this->id, 2, 0, STR_PAD_LEFT), -2)
250: . '/' . $hash;
251: }
252:
253: 254: 255: 256: 257: 258: 259:
260: public function getVFSName($view)
261: {
262: $vfsname = $this->id;
263:
264: if ($view == 'full' && $this->type) {
265: $type = strpos($this->type, '/') === false ?
266: 'image/' . $this->type :
267: $this->type;
268: if ($ext = Horde_Mime_Magic::mimeToExt($type)) {
269: $vfsname .= '.' . $ext;
270: }
271: } elseif (($GLOBALS['conf']['image']['type'] == 'jpeg') || $view == 'screen') {
272: $vfsname .= '.jpg';
273: } else {
274: $vfsname .= '.png';
275: }
276:
277: return $vfsname;
278: }
279:
280: 281: 282: 283: 284: 285: 286: 287:
288: public function load($view = 'full', Ansel_Style $style = null)
289: {
290:
291:
292:
293: if ($view == 'full' && !empty($this->_data['full'])) {
294: $this->_image->loadString($this->_data['full']);
295: $this->_loaded['full'] = true;
296: return;
297: } elseif ($view == 'full') {
298: try {
299: $data = $GLOBALS['injector']
300: ->getInstance('Horde_Core_Factory_Vfs')
301: ->create('images')
302: ->read($this->getVFSPath('full'), $this->getVFSName('full'));
303: } catch (Horde_Vfs_Exception $e) {
304: Horde::logMessage($e, 'ERR');
305: throw new Ansel_Exception($e);
306: }
307: $viewHash = 'full';
308: } else {
309: $viewHash = $this->getViewHash($view, $style);
310:
311:
312: if (!empty($this->_loaded[$viewHash])) {
313: return;
314: }
315: $this->createView($view, $style);
316:
317:
318:
319: if (!empty($this->_loaded[$viewHash])) {
320: return;
321: }
322:
323:
324: $vfspath = $this->getVFSPath($view, $style);
325:
326:
327: try {
328: $data = $GLOBALS['injector']
329: ->getInstance('Horde_Core_Factory_Vfs')
330: ->create('images')
331: ->read($vfspath, $this->getVFSName($view));
332: } catch (Horde_Vfs_Exception $e) {
333: Horde::logMessage($e, 'ERR');
334: throw new Ansel_Exception($e);
335: }
336: }
337:
338:
339: $this->_loaded[$viewHash] = true;
340: $this->_data[$viewHash] = $data;
341: $this->_image->loadString($data);
342: }
343:
344: 345: 346: 347: 348: 349: 350: 351: 352: 353:
354: static public function viewExists($id, $view, Ansel_Style $style)
355: {
356:
357: if (empty($style)) {
358: return false;
359: }
360:
361:
362: $view = $style->getHash($view);
363:
364:
365:
366: $vfspath = '.horde/ansel/' . substr(str_pad($id, 2, 0, STR_PAD_LEFT), -2) . '/' . $view;
367:
368:
369: $vfsname = $id . '.';
370: if ($GLOBALS['conf']['image']['type'] == 'jpeg' || $view == 'screen') {
371: $vfsname .= 'jpg';
372: } else {
373: $vfsname .= 'png';
374: }
375:
376: if ($GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')->create('images')->exists($vfspath, $vfsname)) {
377: return $view . '/' . $vfsname;
378: } else {
379: return false;
380: }
381: }
382:
383: 384: 385: 386: 387: 388: 389: 390:
391: public function createView($view, Ansel_Style $style = null)
392: {
393:
394: if (empty($style)) {
395: $style = $GLOBALS['injector']
396: ->getInstance('Ansel_Storage')
397: ->getGallery($this->gallery)
398: ->getStyle();
399: }
400:
401:
402: $vfspath = $this->getVFSPath($view, $style);
403: if ($GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')
404: ->create('images')
405: ->exists($vfspath, $this->getVFSName($view))) {
406: return;
407: }
408: try {
409: $data = $GLOBALS['injector']
410: ->getInstance('Horde_Core_Factory_Vfs')
411: ->create('images')
412: ->read($this->getVFSPath('full'), $this->getVFSName('full'));
413: } catch (Horde_Vfs_Exception $e) {
414: Horde::logMessage($e, 'ERR');
415: throw new Ansel_Exception($e);
416: }
417:
418:
419: if ($view == 'screen' && $GLOBALS['conf']['image']['type'] != 'jpeg') {
420: $originalType = $this->_image->setType('jpeg');
421: } else {
422: $originalType = false;
423: }
424:
425: $vHash = $this->getViewHash($view, $style);
426: $this->_image->loadString($data);
427: if ($view == 'thumb') {
428: $viewType = $style->thumbstyle;
429: } else {
430:
431: $viewType = ucfirst($view);
432: }
433:
434: try {
435: $iview = Ansel_ImageGenerator::factory(
436: $viewType, array('image' => $this, 'style' => $style));
437: } catch (Ansel_Exception $e) {
438:
439:
440: if ($view == 'thumb' && $viewType != 'Thumb') {
441: $iview = Ansel_ImageGenerator::factory(
442: 'Thumb',
443: array(
444: 'image' => $this,
445: 'style' => Ansel::getStyleDefinition('ansel_default')));
446: } else {
447:
448: throw $e;
449: }
450: }
451:
452:
453: $iview->create();
454:
455:
456: try {
457: $this->_data[$vHash] = $this->_image->raw();
458: } catch (Horde_Image_Exception $e) {
459: throw new Ansel_Exception($e);
460: }
461:
462:
463: $this->_image->loadString($this->_data[$vHash]);
464: $this->_loaded[$vHash] = true;
465: $GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')
466: ->create('images')
467: ->writeData($vfspath, $this->getVFSName($vHash), $this->_data[$vHash], true);
468:
469:
470: if ($view == 'screen' &&
471: $GLOBALS['prefs']->getValue('watermark_auto') &&
472: $GLOBALS['prefs']->getValue('watermark_text') != '') {
473:
474: $this->watermark('screen');
475: $GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')
476: ->create('images')
477: ->writeData($vfspath, $this->getVFSName($view), $this->_image->_data);
478: }
479:
480:
481: if ($originalType) {
482: $this->_image->setType($originalType);
483: }
484: }
485:
486: 487: 488: 489: 490: 491:
492: protected function _writeData()
493: {
494: $this->_dirty = false;
495:
496: try {
497: $GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')
498: ->create('images')
499: ->writeData(
500: $this->getVFSPath('full'),
501: $this->getVFSName('full'),
502: $this->_data['full'],
503: true);
504: } catch (Horde_Vfs_Exception $e) {
505: throw new Ansel_Exception($e);
506: }
507:
508: return true;
509: }
510:
511: 512: 513: 514: 515: 516: 517: 518: 519: 520:
521: public function updateData($data, $view = 'full')
522: {
523:
524: if ($view == 'full') {
525: $this->deleteCache();
526: }
527:
528: try {
529: $GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')
530: ->create('images')->writeData(
531: $this->getVFSPath($view),
532: $this->getVFSName($view),
533: $data,
534: true);
535: } catch (Horde_Vfs_Exception $e) {
536: throw new Ansel_Exception($e);
537: }
538: }
539:
540: 541: 542: 543: 544: 545: 546: 547: 548:
549: public function geotag($lat, $lng, $location = '')
550: {
551: $this->lat = $lat;
552: $this->lng = $lng;
553: $this->location = $location;
554: $this->geotag_timestamp = time();
555: $this->save();
556: }
557:
558: 559: 560: 561: 562: 563:
564: public function save()
565: {
566:
567: if ($this->id) {
568: return $GLOBALS['injector']
569: ->getInstance('Ansel_Storage')
570: ->saveImage($this);
571: }
572:
573:
574: $GLOBALS['injector']->getInstance('Ansel_Storage')->saveImage($this);
575:
576:
577: $this->_writeData();
578:
579:
580: if ($this->gallery > 0) {
581: $needUpdate = $this->getEXIF();
582: }
583:
584:
585: $fields = @unserialize($GLOBALS['prefs']->getValue('exif_tags'));
586: if ($fields) {
587: $this->_exifToTags($fields);
588: }
589:
590:
591: if (count($this->_tags)) {
592: try {
593: $this->setTags($this->_tags);
594: } catch (Exception $e) {
595:
596:
597: Horde::logMessage($e, 'ERR');
598: }
599: }
600:
601:
602: if (!empty($needUpdate)) {
603: $GLOBALS['injector']->getInstance('Ansel_Storage')->saveImage($this);
604: }
605:
606: return $this->id;
607: }
608:
609: 610: 611: 612: 613: 614: 615: 616:
617: public function replace(array $imageData)
618: {
619:
620: $this->_data = array();
621: $this->reset();
622:
623:
624: $GLOBALS['injector']
625: ->getInstance('Ansel_Storage')
626: ->clearImageAttributes($this->id);
627:
628:
629: $this->getEXIF();
630: $this->updateData($imageData);
631: }
632:
633: 634: 635: 636: 637: 638: 639: 640:
641: protected function _exifToTags(array $fields = array())
642: {
643: $tags = array();
644: foreach ($fields as $field) {
645: if (!empty($this->_exif[$field])) {
646: if (substr($field, 0, 8) == 'DateTime') {
647: $d = new Horde_Date(strtotime($this->_exif[$field]));
648: $tags[] = $d->format("Y-m-d");
649: } elseif ($field == 'Keywords') {
650: $tags = array_merge($tags, explode(',', $this->_exif[$field]));
651: } else {
652: $tags[] = $this->_exif[$field];
653: }
654: }
655: }
656:
657: $this->_tags = array_merge($this->_tags, $tags);
658: }
659:
660: 661: 662: 663: 664: 665: 666: 667: 668: 669:
670: public function getEXIF($replacing = false)
671: {
672:
673: $this->_exif = array();
674:
675:
676: try {
677: $imageFile = $GLOBALS['injector']
678: ->getInstance('Horde_Core_Factory_Vfs')
679: ->create('images')
680: ->readFile(
681: $this->getVFSPath('full'),
682: $this->getVFSName('full'));
683: } catch (Horde_Vfs_Exception $e) {
684: throw new Ansel_Exception($e);
685: }
686: $exif = Horde_Image_Exif::factory(
687: $GLOBALS['conf']['exif']['driver'],
688: !empty($GLOBALS['conf']['exif']['params']) ?
689: $GLOBALS['conf']['exif']['params'] :
690: array());
691:
692: try {
693: $exif_fields = $exif->getData($imageFile);
694: } catch (Horde_Image_Exception $e) {
695:
696: Horde::logMessage($e, 'ERR');
697: $exif_fields = array();
698: return false;
699: }
700:
701:
702: $needUpdate = false;
703:
704:
705: if (!empty($exif_fields['GPSLatitude'])) {
706: $this->lat = $exif_fields['GPSLatitude'];
707: $this->lng = $exif_fields['GPSLongitude'];
708: $this->geotag_timestamp = time();
709: $needUpdate = true;
710: }
711:
712: if (!empty($exif_fields['DateTimeOriginal'])) {
713: $this->originalDate = $exif_fields['DateTimeOriginal'];
714: $needUpdate = true;
715: }
716:
717:
718: $exif_title = $GLOBALS['prefs']->getValue('exif_title');
719: if (!empty($exif_fields[$exif_title])) {
720: $this->caption = $exif_fields[$exif_title];
721: $needUpdate = true;
722: }
723:
724:
725: $this->_autoRotate($exif_fields['Orientation']);
726:
727:
728: if ($replacing) {
729: $GLOBALS['injector']
730: ->getInstance('Ansel_Storage')
731: ->clearImageAttributes($this->id);
732: }
733:
734: foreach ($exif_fields as $name => $value) {
735: if (!empty($value)) {
736: $GLOBALS['injector']
737: ->getInstance('Ansel_Storage')
738: ->saveImageAttribute($this->id, $name, $value);
739: $this->_exif[$name] = Horde_Image_Exif::getHumanReadable($name, $value);
740: }
741: }
742:
743: return $needUpdate;
744: }
745:
746: 747: 748: 749:
750: protected function _autoRotate($orientation)
751: {
752: if (!empty($orientation) && $orientation != 1) {
753: switch ($orientation) {
754: case 2:
755: $this->mirror();
756: break;
757:
758: case 3:
759: $this->rotate('full', 180);
760: break;
761:
762: case 4:
763: $this->mirror();
764: $this->rotate('full', 180);
765: break;
766:
767: case 5:
768: $this->flip();
769: $this->rotate('full', 90);
770: break;
771:
772: case 6:
773: $this->rotate('full', 90);
774: break;
775:
776: case 7:
777: $this->mirror();
778: $this->rotate('full', 90);
779: break;
780:
781: case 8:
782: $this->rotate('full', 270);
783: break;
784: }
785:
786: if ($this->_dirty) {
787: $this->_data['full'] = $this->raw();
788: $this->_writeData();
789: }
790: }
791: }
792:
793: 794: 795: 796:
797: public function reset()
798: {
799: $this->_image->reset();
800: $this->_loaded = array();
801: }
802:
803: 804: 805: 806: 807: 808: 809:
810: public function deleteCache($view = 'all')
811: {
812:
813: if ($view == 'all' || $view == 'screen') {
814: try {
815: $GLOBALS['injector']
816: ->getInstance('Horde_Core_Factory_Vfs')
817: ->create('images')
818: ->deleteFile(
819: $this->getVFSPath('screen'),
820: $this->getVFSName('screen'));
821: } catch (Horde_Vfs_Exception $e ) {}
822: }
823:
824:
825: if ($view == 'all' || $view == 'mini') {
826: try {
827: $GLOBALS['injector']
828: ->getInstance('Horde_Core_Factory_Vfs')
829: ->create('images')
830: ->deleteFile(
831: $this->getVFSPath('mini'),
832: $this->getVFSName('mini'));
833: } catch (Horde_Vfs_Exception $e) {}
834: }
835: if ($view == 'all' || $view == 'thumb') {
836: $hashes = $GLOBALS['injector']
837: ->getInstance('Ansel_Storage')
838: ->getHashes();
839: foreach ($hashes as $hash) {
840: try {
841: $GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')
842: ->create('images')
843: ->deleteFile(
844: $this->getVFSPathFromHash($hash),
845: $this->getVFSName('thumb'));
846: } catch (Horde_Vfs_Exception $e) {}
847: }
848: }
849: }
850:
851: 852: 853: 854: 855: 856: 857:
858: public function raw($view = 'full')
859: {
860: if ($this->_dirty) {
861: $data = $this->_image->raw( );
862: $this->reset();
863: return $data;
864: } else {
865: $this->load($view);
866: return $this->_data[$view];
867: }
868: }
869:
870: 871: 872: 873: 874:
875: public function ($view = 'full')
876: {
877: global $browser, $conf;
878:
879: $filename = $this->filename;
880: if ($view != 'full') {
881: if ($ext = Horde_Mime_Magic::mimeToExt('image/' . $conf['image']['type'])) {
882: $filename .= '.' . $ext;
883: }
884: }
885:
886: $browser->downloadHeaders($filename);
887: }
888:
889: 890: 891: 892: 893: 894: 895: 896:
897: public function display($view = 'full', Ansel_Style $style = null)
898: {
899: if ($view == 'full' && !$this->_dirty) {
900:
901: $gallery = $GLOBALS['injector']
902: ->getInstance('Ansel_Storage')
903: ->getGallery($this->gallery);
904: if (!$gallery->canDownload()) {
905: throw Horde_Exception_PermissionDenied(
906: sprintf(_("Access denied downloading photos from \"%s\"."), $gallery->get('name')));
907: }
908:
909: try {
910: $data = $GLOBALS['injector']
911: ->getInstance('Horde_Core_Factory_Vfs')
912: ->create('images')->read(
913: $this->getVFSPath('full'),
914: $this->getVFSName('full'));
915: } catch (Horde_Vfs_Exception $e) {
916: throw new Ansel_Exception($e);
917: }
918: echo $data;
919: } else {
920: $this->load($view, $style);
921: $this->_image->display();
922: }
923: }
924:
925: 926: 927: 928: 929: 930: 931:
932: public function toFile($view = 'full')
933: {
934: try {
935: $this->load($view);
936: return $this->_image->toFile(
937: $this->_dirty ?
938: false :
939: $this->_data[$view]);
940: } catch (Horde_Exception $e) {
941: Horde::logMessage($e, 'ERR');
942: throw new Ansel_Exception($e);
943: }
944: }
945:
946: 947: 948: 949: 950: 951: 952: 953:
954: public function getDimensions($view = 'full')
955: {
956: try {
957: $this->load($view);
958: return $this->_image->getDimensions();
959: } catch (Horde_Exception $e) {
960: Horde::logMessage($e, 'INFO');
961: throw new Ansel_Exception($e);
962: }
963: }
964:
965: 966: 967: 968: 969: 970:
971: public function rotate($view = 'full', $angle)
972: {
973: $this->load($view);
974: $this->_dirty = true;
975: $this->_image->rotate($angle);
976: }
977:
978: 979: 980: 981: 982: 983: 984: 985: 986: 987: 988: 989: 990:
991: public function crop($x1, $y1, $x2, $y2)
992: {
993: $this->_dirty = true;
994: try {
995: $this->_image->crop($x1, $y1, $x2, $y2);
996: } catch (Horde_Image_Exception $e) {
997: throw new Ansel_Exception($e);
998: }
999: }
1000:
1001: 1002: 1003: 1004: 1005: 1006: 1007: 1008: 1009: 1010:
1011: public function resize($width, $height, $ratio = true, $keepProfile = false)
1012: {
1013: try {
1014: $this->_image->resize($width, $height, $ratio, $keepProfile);
1015: } catch (Horde_Image_Exception $e) {
1016: throw new Ansel_Exception($e);
1017: }
1018: }
1019:
1020: 1021: 1022: 1023: 1024: 1025: 1026:
1027: public function grayscale($view = 'full')
1028: {
1029: $this->load($view);
1030: $this->_dirty = true;
1031: try {
1032: $this->_image->grayscale();
1033: } catch (Horde_Image_Exception $e) {
1034: throw new Ansel_Exception($e);
1035: }
1036: }
1037:
1038: 1039: 1040: 1041: 1042: 1043: 1044: 1045: 1046: 1047: 1048: 1049:
1050: public function watermark($view = 'full', $watermark = null, $halign = null,
1051: $valign = null, $font = null)
1052: {
1053: if (empty($watermark)) {
1054: $watermark = $GLOBALS['prefs']->getValue('watermark_text');
1055: }
1056: if (empty($halign)) {
1057: $halign = $GLOBALS['prefs']->getValue('watermark_horizontal');
1058: }
1059: if (empty($valign)) {
1060: $valign = $GLOBALS['prefs']->getValue('watermark_vertical');
1061: }
1062: if (empty($font)) {
1063: $font = $GLOBALS['prefs']->getValue('watermark_font');
1064: }
1065: if (empty($watermark)) {
1066: $identity = $GLOBALS['injector']
1067: ->getInstance('Horde_Core_Factory_Identity')
1068: ->create();
1069: $name = $identity->getValue('fullname');
1070: if (empty($name)) {
1071: $name = $GLOBALS['registry']->getAuth();
1072: }
1073: $watermark = sprintf(_("(c) %s %s"), date('Y'), $name);
1074: }
1075:
1076: $this->load($view);
1077: $this->_dirty = true;
1078: $params = array(
1079: 'text' => $watermark,
1080: 'halign' => $halign,
1081: 'valign' => $valign,
1082: 'fontsize' => $font);
1083: if (!empty($GLOBALS['conf']['image']['font'])) {
1084: $params['font'] = $GLOBALS['conf']['image']['font'];
1085: }
1086:
1087: try {
1088: $this->_image->addEffect('TextWatermark', $params);
1089: } catch (Horde_Image_Exception $e) {
1090: throw new Ansel_Exception($e);
1091: }
1092: }
1093:
1094: 1095: 1096: 1097: 1098: 1099: 1100:
1101: public function flip($view = 'full')
1102: {
1103: $this->load($view);
1104: $this->_dirty = true;
1105:
1106: try {
1107: $this->_image->flip();
1108: } catch (Horde_Image_Exception $e) {
1109: throw new Ansel_Exception($e);
1110: }
1111: }
1112:
1113: 1114: 1115: 1116: 1117: 1118: 1119:
1120: public function mirror($view = 'full')
1121: {
1122: $this->load($view);
1123: $this->_dirty = true;
1124: try {
1125: $this->_image->mirror();
1126: } catch (Horde_Image_Exception $e) {
1127: throw new Ansel_Exception($e);
1128: }
1129: }
1130:
1131: 1132: 1133: 1134: 1135: 1136: 1137: 1138:
1139: public function addEffect($type, $params = array())
1140: {
1141: try {
1142: $this->_image->addEffect($type, $params);
1143: } catch (Horde_Image_Exception $e) {
1144: Horde::logMessage($e, 'ERR');
1145: throw new Ansel_Exception($e);
1146: }
1147: }
1148:
1149: 1150: 1151: 1152: 1153:
1154: public function applyEffects()
1155: {
1156: try {
1157: $this->_image->applyEffects();
1158: } catch (Horde_Image_Exception $e) {
1159: throw new Ansel_Exception($e);
1160: }
1161: }
1162:
1163: 1164: 1165: 1166: 1167: 1168: 1169: 1170:
1171: public function getTags()
1172: {
1173: if (count($this->_tags)) {
1174: return $this->_tags;
1175: }
1176: $gallery = $GLOBALS['injector']->getInstance('Ansel_Storage')
1177: ->getGallery($this->gallery);
1178: if ($gallery->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::READ)) {
1179: return $GLOBALS['injector']->getInstance('Ansel_Tagger')
1180: ->getTags($this->id, 'image');
1181: } else {
1182: throw new Horde_Exception_PermissionDenied(
1183: _("Access denied viewing this photo."));
1184: }
1185: }
1186:
1187: 1188: 1189: 1190: 1191: 1192: 1193: 1194:
1195: public function setTags(array $tags, $replace = true)
1196: {
1197: $gallery = $GLOBALS['injector']
1198: ->getInstance('Ansel_Storage')
1199: ->getGallery(abs($this->gallery));
1200: if ($gallery->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::EDIT)) {
1201: $this->_tags = array();
1202:
1203: if ($replace) {
1204: $GLOBALS['injector']
1205: ->getInstance('Ansel_Tagger')
1206: ->replaceTags(
1207: (string)$this->id,
1208: $tags,
1209: $gallery->get('owner'),
1210: 'image');
1211: } else {
1212: $GLOBALS['injector']
1213: ->getInstance('Ansel_Tagger')
1214: ->tag(
1215: (string)$this->id,
1216: $tags,
1217: $gallery->get('owner'),
1218: 'image');
1219: }
1220: } else {
1221: throw new Horde_Exception_PermissionDenied(_("Access denied adding tags to this photo."));
1222: }
1223: }
1224:
1225: 1226: 1227: 1228: 1229:
1230: public function removeTag($tag)
1231: {
1232: $gallery = $GLOBALS['injector']
1233: ->getInstance('Ansel_Storage')
1234: ->getGallery(abs($this->gallery));
1235: if ($gallery->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::EDIT)) {
1236: $GLOBALS['injector']
1237: ->getInstance('Ansel_Tagger')
1238: ->untag(
1239: (string)$this->id,
1240: $tag);
1241: }
1242: }
1243:
1244: 1245: 1246: 1247: 1248: 1249: 1250: 1251: 1252: 1253: 1254:
1255: public function getTile(Ansel_Gallery $parent = null,
1256: Ansel_Style $style = null,
1257: $mini = false,
1258: array $params = array())
1259: {
1260: if (!is_null($parent) && is_null($style)) {
1261: $style = $parent->getStyle();
1262: }
1263:
1264: return Ansel_Tile_Image::getTile($this, $style, $mini, $params);
1265: }
1266:
1267: 1268: 1269: 1270: 1271:
1272: public function getType($view = 'full')
1273: {
1274: if ($view == 'full') {
1275: return $this->type;
1276: } elseif ($view == 'screen') {
1277: return 'image/jpg';
1278: } else {
1279: return 'image/' . $GLOBALS['conf']['image']['type'];
1280: }
1281: }
1282:
1283: 1284: 1285: 1286: 1287: 1288: 1289: 1290:
1291: public function getViewHash($view, Ansel_Style $style = null)
1292: {
1293:
1294: if ($view == 'screen' || $view == 'mini' || $view == 'full') {
1295: return $view;
1296: }
1297:
1298: if (is_null($style)) {
1299: $gallery = $GLOBALS['injector']->getInstance('Ansel_Storage')
1300: ->getGallery(abs($this->gallery));
1301: $style = $gallery->getStyle();
1302: }
1303:
1304: return $style->getHash($view);
1305: }
1306:
1307: 1308: 1309: 1310: 1311: 1312: 1313: 1314:
1315: public function getAttributes($format = false)
1316: {
1317: $attributes = $GLOBALS['injector']->getInstance('Ansel_Storage')
1318: ->getImageAttributes($this->id);
1319: $exif = Horde_Image_Exif::factory(
1320: $GLOBALS['conf']['exif']['driver'],
1321: !empty($GLOBALS['conf']['exif']['params']) ?
1322: $GLOBALS['conf']['exif']['params'] :
1323: array());
1324: $fields = Horde_Image_Exif::getFields($exif);
1325: $output = array();
1326:
1327: foreach ($fields as $field => $data) {
1328: if (!isset($attributes[$field])) {
1329: continue;
1330: }
1331: $value = Horde_Image_Exif::getHumanReadable(
1332: $field,
1333: Horde_String::convertCharset($attributes[$field], $GLOBALS['conf']['sql']['charset'], 'UTF-8'));
1334: if (!$format) {
1335: $output[$field] = $value;
1336: } else {
1337: $description = isset($data['description']) ? $data['description'] : $field;
1338: $output[] = '<td><strong>' . $description . '</strong></td><td>' . htmlspecialchars($value) . '</td>';
1339: }
1340: }
1341:
1342: return $output;
1343: }
1344:
1345: 1346: 1347: 1348: 1349: 1350:
1351: public function isMultiPage()
1352: {
1353: $this->load();
1354: try {
1355: return $this->_image->getImagePageCount() > 1;
1356: } catch (Horde_Image_Exception $e) {
1357: throw new Ansel_Exception($e);
1358: }
1359: }
1360:
1361: 1362: 1363: 1364: 1365: 1366:
1367: public function getImagePageCount()
1368: {
1369: if (empty($this->_loaded['full'])) {
1370: $this->load();
1371: }
1372:
1373: try {
1374: return $this->_image->getImagePageCount();
1375: } catch (Horde_Image_Exception $e) {
1376: throw new Ansel_Exception($e);
1377: }
1378: }
1379:
1380: 1381: 1382: 1383: 1384: 1385:
1386: public function rewind()
1387: {
1388: if (empty($this->_loaded['full'])) {
1389: $this->load();
1390: }
1391: try {
1392: $this->_image->rewind();
1393: } catch (Horde_Image_Exception $e) {
1394: throw new Ansel_Exception($e);
1395: }
1396: }
1397:
1398: 1399: 1400: 1401: 1402:
1403: public function current()
1404: {
1405: if (empty($this->_loaded['full'])) {
1406: $this->load();
1407: }
1408: try {
1409: return $this->_buildImageObject($this->_image->current());
1410: } catch (Horde_Image_Exception $e) {
1411: throw new Ansel_Exception($e);
1412: }
1413: }
1414:
1415: 1416: 1417: 1418: 1419: 1420:
1421: public function key()
1422: {
1423: if (empty($this->_loaded['full'])) {
1424: $this->load();
1425: }
1426: try {
1427: return $this->_image->key();
1428: } catch (Horde_Image_Exception $e) {
1429: throw new Ansel_Exception($e);
1430: }
1431: }
1432:
1433: 1434: 1435: 1436: 1437:
1438: public function next()
1439: {
1440: if (empty($this->_loaded['full'])) {
1441: $this->load();
1442: }
1443: if ($next = $this->_image->next()) {
1444: return $this->_buildImageObject($next);
1445: }
1446:
1447: return false;
1448: }
1449:
1450: 1451: 1452: 1453: 1454: 1455:
1456: public function valid()
1457: {
1458: if (empty($this->_loaded['full'])) {
1459: $this->load();
1460: }
1461: try {
1462: return $this->_image->valid();
1463: } catch (Horde_Image_Exception $e) {
1464: throw new Ansel_Exception($e);
1465: }
1466: }
1467:
1468: 1469: 1470: 1471: 1472: 1473: 1474: 1475:
1476: protected function _buildImageObject(Horde_Image_Base $image)
1477: {
1478: $params = array(
1479: 'image_filename' => $this->filename,
1480: 'data' => $image->raw(),
1481: );
1482: $newImage = new Ansel_Image($params);
1483:
1484: return $newImage;
1485: }
1486: }
1487: