Project

General

Profile

Download (19.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
// $Id$
3

    
4
/**
5
 * Copyright (C) 2007 EDIT
6
 * European Distributed Institute of Taxonomy
7
 * http://www.e-taxonomy.eu
8
 *
9
 * The contents of this file are subject to the Mozilla Public License Version 1.1
10
 * See http://www.mozilla.org/MPL/MPL-1.1.html for the full license terms.
11
 */
12

    
13
function media_content_type_dir($media_representation, $default = false){
14

    
15
	if($media_representation->mimeType){
16
		return substr($media_representation->mimeType, 0, stripos($media_representation->mimeType, '/'));
17
	} else {
18
		return $default;
19
	}
20
}
21

    
22
function getimagesize_remote($image_url) {
23

    
24
	$contents = cdm_http_request($image_url);
25
	if(!$contents){
26
		return false;
27
	}
28

    
29
	$im = @ImageCreateFromString($contents); // using@ to avoid php user warnings
30
	if (!$im) {
31
		return false;
32
	}
33
	$gis[0] = ImageSX($im);
34
	$gis[1] = ImageSY($im);
35
	// array member 3 is used below to keep with current getimagesize standards
36
	$gis[3] = "width={$gis[0]} height={$gis[1]}";
37
	ImageDestroy($im);
38
	return $gis;
39
}
40

    
41

    
42

    
43
function theme_cdm_media($descriptionElement, $mimeTypePreference){
44
	$out = "";
45

    
46
	_add_js_thickbox();
47

    
48
	$uuid = $descriptionElement->uuid;
49
	$feature = $descriptionElement->feature;
50
	$medias = $descriptionElement->media;
51

    
52
	foreach($medias as $media){
53
		$prefRepresentations = cdm_preferred_media_representations($media, $mimeTypePreference, 300, 400);
54
		$mediaRepresentation = array_shift($prefRepresentations);
55
		if($mediaRepresentation) {
56

    
57
			$contentTypeDirectory = media_content_type_dir($mediaRepresentation);
58

    
59
			$out .= theme('cdm_media_mime_' . $contentTypeDirectory,  $mediaRepresentation, $feature);
60

    
61
			//			$attributes = array('class'=>'thickbox', 'rel'=>'descriptionElement-'.$uuid, 'title'=>$feature->term);
62
			//		    for($i = 0; $part = $mediaRepresentation->representationParts[$i]; $i++){
63
			//		    	if($i == 0){
64
			//		    	    $image_url = drupal_get_path('module', 'cdm_dataportal').'/images/'.$feature->term.'-media.png';
65
			//		    	    $media = '<img src="'.$image_url.'" height="14px" alt="'.$feature->term.'" />';
66
			//		    	    $out .= l($media, $part->uri, $attributes, NULL, NULL, TRUE, TRUE);
67
			//		    	} else {
68
			//		    		$out .= l('', $part->uri, $attributes, NULL, NULL, TRUE);
69
			//		    	}
70
			//		  	}
71
		} else {
72
			// no media available, so display just the type term
73
			$out .=  $feature->representation_L10n;
74
		}
75
	}
76
	return $out;
77

    
78
}
79

    
80
function theme_cdm_mediaTypeTerm($feature, $mediaUrl = false){
81

    
82
	$provider = '';
83
	//TODO directly use favicon from referred URI and overlay on $icon_image, but for now we comment this out
84
	//	if(strpos($mediaUrl, 'biodiversitylibrary.org') > 0){
85
	//    $provider = '-BHL';
86
	//	}
87

    
88
	$icon_image = $feature->representation_L10n.'-media'.$provider.'.png';
89
	$icon_url = drupal_get_path('module', 'cdm_dataportal').'/images/'.$icon_image;
90
	return '<img src="'.$icon_url.'" height="14px" alt="'.$feature->representation_L10n.'" />';
91
}
92

    
93
function theme_cdm_media_mime_application($mediaRepresentation, $feature){
94

    
95
	foreach($mediaRepresentation->parts as $part){
96
		$attributes = array('title'=> theme('cdm_feature_name', $feature->representation_L10n), 'target'=>'_blank');
97
		//$attributes = array('title'=>$feature->representation_L10n, 'target'=>'_blank');
98
		//$attributes = array('title'=>'original publication', 'target'=>'_blank');
99
		$out .= l(theme('cdm_mediaTypeTerm', $feature, $part->uri), $part->uri, $attributes, NULL, NULL, TRUE, TRUE);
100
	}
101
	return $out;
102
}
103

    
104
function theme_cdm_media_mime_image($mediaRepresentation, $feature){
105
	$out = '';
106
	//TODO thickbox is not used anymore -> delete ?
107
	$attributes = array('class'=>'thickbox', 'rel'=>'representation-'.$representation->uuid, 'title'=>$feature->representation_L10n);
108
	for($i = 0; $part = $representation->representationParts[$i]; $i++){
109
		if($i == 0){
110
			$out .= l(theme('cdm_mediaTypeTerm', $feature, $part->uri), $part->uri, $attributes, NULL, NULL, TRUE, TRUE);
111
		} else {
112
			$out .= l('', $part->uri, $attributes, NULL, NULL, TRUE);
113
		}
114
	}
115
	return $out;
116
}
117

    
118
function theme_cdm_media_mime_text($representation, $feature){
119

    
120
	foreach($representation->parts as $part){
121
		$attributes = array('title'=> theme('cdm_feature_name', $feature->representation_L10n), 'target'=>'_blank');
122
		//$attributes = array('title'=>t('original publication'), 'target'=>'_blank');
123
		$out .= l(theme('cdm_mediaTypeTerm', $feature, $part->uri), $part->uri, $attributes, NULL, NULL, TRUE, TRUE);
124
	}
125
	return $out;
126
}
127

    
128

    
129
function theme_cdm_media_caption($media, $elements = array('title', 'description', 'artist', 'location', 'rights'), $fileUri = null){
130

    
131
	$media_metadata = cdm_read_media_metadata($media);
132

    
133
	$out = '<dl class="media-caption">';
134
	//title
135
	if($media_metadata['title'] && (!$elements || array_search('title', $elements)!== false)){
136
		$out .= '<dt class = "title">' . t('Title') . '</dt> <dd class = "title">' . $media_metadata['title'] . '</dd>';
137
		//unset($media_metadata['title']);
138
	}
139
	//description
140
	if($media_metadata['description'] && (!$elements || array_search('description', $elements)!== false)){
141
		$out .= '<dt class = "description">' . t('Description') . '</dt> <dd class = "description">' . $media_metadata['description'] . '</dd>';
142
		//unset($media_metadata['description']);
143
	}
144
	//artist
145
	if($media_metadata['artist'] && (!$elements || array_search('artist', $elements)!== false)){
146
		//$out .= '<span class = "artist">' . ($media_metadata['artist'] ? 'Artist: ' . $media_metadata['artist'] . '</span>' . '<br>' : '');
147
		$out .= '<dt class = "artist">' . t('Artist') . '</dt> <dd class = "astist">' . $media_metadata['artist'] . '</dd>';
148
	}
149
	//location
150
	if(!$elements || array_search('location', $elements)!== false){
151
		$location = '';
152
		$location .= $media_metadata['location']['sublocation'];
153
		if ($location && $media_metadata['location']['city']){
154
			$location .= ', ';
155
		}
156
		$location .= $media_metadata['location']['city'];
157
		if ($location && $media_metadata['location']['province']){
158
			$location .= ', ';
159
		}
160
		$location .= $media_metadata['location']['province'];
161
		if ($location && $media_metadata['location']['country']){
162
			$location .= ' (' . $media_metadata['location']['country'] . ')';
163
		} else {
164
			$location .= $media_metadata['location']['country'];
165
		}
166
		if ($location){
167
			$out .= '<dt class = "location">' . t('Location') . '</dt> <dd class = "location">' . $location  . '</dd>';
168
		}
169
	}
170
	//rights
171
	if(!$elements || array_search('rights', $elements)!== false){
172
		$rights = '';
173
		//copyrights
174
		$cnt = count($media_metadata['rights']['copyright']['agentNames']);
175
		if($cnt > 0){
176
			$rights .= '<dt class="rights">&copy;</dt> <dd class="rights"> ';
177
			for($i = 0; $i < $cnt; $i++){
178
				$rights .= $media_metadata['rights']['copyright']['agentNames'][$i];
179
				if($i+1 < $cnt){
180
					$rights .= ' / ';
181
				}
182
			}
183
			$rights .= '</dd>';
184
		}
185
		//license
186
		$cnt = count($media_metadata['rights']['license']['agentNames']);
187
		if($cnt > 0){
188
			$rights .= '<dt class ="license">' . t('License') . '</dt> <dd class = "license">';
189
			for($i = 0; $i < $cnt; $i++){
190
				$rights .= $media_metadata['rights']['license']['agentNames'][$i];
191
				if ($i+1 < $cnt){
192
					$rights .= ' / ';
193
				}
194
			}
195
			$rights .= '</dd>';
196
		}
197
		if($rights){
198
			$out .=  $rights . '</dt>';
199
		}
200
	}
201
	//TODO add all other metadata elemenst generically
202
	$out .= '</dl>';
203
	//return value
204
	return $out;
205
}
206

    
207

    
208
/**
209
 * @param $mediaList an array of Media entities
210
 * @param $maxExtend
211
 * @param $cols
212
 * @param $maxRows
213
 * @param $captionElements an array possible values are like in the following example: array('title', 'description', 'file', 'filename'),
214
 *         to add a link to the caption: array('titlecache', '#uri'=>t('open Image'));
215
 * @param $mediaLinkType valid values:
216
 *      "NONE": do not link the images,
217
 *      "LIGHTBOX": open the link in a light box,
218
 *      "NORMAL": link to the image page or to the $alternativeMediaUri if it is defined
219
 * @param $alternativeMediaUri an array of alternative URIs to link the images wich will overwrite the URIs of the media parts.
220
 *     The order of URI in this array must correspond with the order of images in $mediaList
221
 * @param $galleryLinkUri an URI to link the the hint on more images to; if null no link is created
222
 * @return unknown_type
223
 */
224
function theme_cdm_media_gallerie(
225
	$mediaList,
226
    $galleryName,
227
	$maxExtend = 150,
228
	$cols = 4,
229
	$maxRows = false,
230
	$captionElements = array('title'),
231
	$mediaLinkType = 'LIGHTBOX',
232
	$alternativeMediaUri = null,
233
	$galleryLinkUri = null,
234
	$showCaption = true){
235

    
236
	if(!is_array($captionElements)){
237
		$captionElements = array();
238
	}
239
	//TODO correctly handle multiple media representation parts
240
	$_SESSION['cdm']['last_gallery']= substr($_SERVER['REQUEST_URI'],strpos($_SERVER['REQUEST_URI'], "?q=")+3);
241
	// prevent from errors
242
	if(!isset($mediaList[0])){
243
		return;
244
	}
245

    
246
	$galleryID = "media_gallery_".$galleryName;
247
	$mediaPartLinkAttributes = array();
248
	$openMediaLinkAttributes = array();
249

    
250
	// prepare media links
251
	$doLink = false;
252
	if($mediaLinkType != 'NONE'){
253
		$doLink = true;
254
	}
255
	if($mediaLinkType == 'LIGHTBOX'){
256
		$doLink = true;
257
		_add_js_lightbox($galleryID);
258
	}
259

    
260
	// render the media gallery grid
261
	$out = '<table id="'.$galleryID.'" class="media_gallery">';
262
	$out .= '<colgroup>';
263
	for($c = 0; $c < $cols; $c++){
264
		$out .= '<col width="'.(100 / $cols).'%">';
265
	}
266
	$out .= '</colgroup>';
267
	for($r = 0; ($r < $maxRows || !$maxRows) && count($mediaList) > 0; $r++){
268
		$captionParts = array();
269
		$out .= '<tr>';
270
		for($c = 0; $c < $cols; $c++){
271
			$media = array_shift($mediaList);
272
			if(isset($media->representations[0]->parts[0])){
273

    
274
				//
275
				// find preferred representation
276
				//
277
				$preferred_media_representations_list = cdm_preferred_media_representations(
278
				$media,
279
				array('image/jpg', 'image/jpeg', 'image/png', 'image/gif'),
280
				$maxExtend, $maxExtend);
281
				if(count($preferred_media_representations_list) == 0){
282
					// fallback to using the first one in the list
283
					$preferred_media_representations_list = $media->representations;
284
				}
285
				$preferred_media_representation = array_shift($preferred_media_representations_list);
286

    
287
				// $preferred_media_representation->parts[0]->uri = "http://127.0.0.1/images/palmae/palm_tc_14415_1.jpg";
288
				$contentTypeDirectory = media_content_type_dir($preferred_media_representation, 'application');
289
				$mediaIndex++;
290
				$mediaPartHtml = theme('cdm_media_gallerie_'.$contentTypeDirectory, $preferred_media_representation->parts[0], $maxExtend, TRUE);
291
				// --- compose Media Link
292
				$mediaLinkUri = false;
293
				if($alternativeMediaUri){
294
					if(isset($alternativeMediaUri[$mediaIndex])){
295
						$mediaLinkUri = $alternativeMediaUri[$mediaIndex];
296
					}
297
					if(is_string($alternativeMediaUri)){
298
						$mediaLinkUri = $alternativeMediaUri;
299
					}
300
				} else {
301
					$mediaLinkUri = $preferred_media_representation->parts[0]->uri;
302
				}
303

    
304
				_add_js_ahah();
305
				$content_url = cdm_compose_url(CDM_WS_PORTAL_MEDIA, $media->uuid);
306

    
307
				$cdm_proxy_url = url('cdm_api/proxy/'.urlencode($content_url)."/cdm_media_caption/".serialize($captionElements));
308
				$captionPartHtml = '<div class="ahah-content" rel="'.$cdm_proxy_url.'"><span class="loading" style="display: none;">Loading ....</span></div>';
309

    
310
				// generate gallery caption
311
				if($mediaLinkType == 'LIGHTBOX' && $contentTypeDirectory == 'image'){
312
					$mediaPartLinkAttributes['class'] = "lightbox";
313
				} else {
314
					$mediaPartLinkAttributes['target'] = "specimen";
315
					$openMediaLinkAttributes['target'] = "specimen";
316
				}
317
				// generate & add caption to lightbox
318
				$lightBoxCaptionElements = null;
319
				$cdm_proxy_url = url('cdm_api/proxy/'.urlencode($content_url)."/cdm_media_caption"); //.($lightBoxCaptionElements?'/'.join	(',',$lightBoxCaptionElements):''));
320
				$mediaPartLinkAttributes['alt'] = '<div class="ahah-content" rel="'.$cdm_proxy_url.'"><span class="loading" style="display: none;">Loading ....</span></div>';
321

    
322
				if(isset($captionElements['#uri'])){
323
					if($contentTypeDirectory == 'image'){
324
						$captionPartHtml .= '<div>'.l($captionElements['#uri'], path_to_media($media->uuid), null, null, null, FALSE, TRUE).'</div>';
325
					} else {
326
						$captionPartHtml .= '<div>'.l($captionElements['#uri'], $mediaLinkUri, $openMediaLinkAttributes, null, null, TRUE, TRUE).'</div>';
327
					}
328
				}
329
				$captionParts[] = $captionPartHtml;
330

    
331
				// --- surround imagePart with link
332
				if($doLink){
333
					$mediaPartHtml = l($mediaPartHtml, $mediaLinkUri, $mediaPartLinkAttributes, null, null, FALSE, TRUE);
334
				}
335

    
336
			} else {
337
				$mediaPartHtml = '';
338
				$captionParts[] = '';
339
			}
340
			$out .= '<td>'.$mediaPartHtml.'</td>';
341
		}
342
		$out .= '</tr>'; // end of media parts
343
		if ($showCaption){
344
		     if(count($captionElements) > 0){
345
            $out .= '<tr>';
346
            // add caption row
347
            foreach($captionParts as $captionPartHtml){
348
                $out .= '<td>'.$captionPartHtml.'</td>';
349
            }
350
            $out .= '</tr>';
351
            }
352
		}
353
	}
354
	if($galleryLinkUri){
355
		if(count($mediaList) > 0){
356
			$moreHtml = count($mediaList).' '.t('more in gallery');
357
		} else {
358
			$moreHtml = t('open gallery');
359
		}
360
		$moreHtml = l($moreHtml, $galleryLinkUri);
361
		$out .= '<tr><td colspan="'.$cols.'">'.$moreHtml.'</td></tr>';
362
	}
363
	$out .= '</table>';
364
	return $out;
365
}
366

    
367
function theme_cdm_media_gallerie_image($mediaRepresentationPart, $maxExtend, $addPassePartout = FALSE, $attributes = null){
368
	//TODO merge with theme_cdm_media_mime_image?
369

    
370
	if(isset($mediaRepresentationPart)){
371

    
372
		$h = $mediaRepresentationPart->height;
373
		$w = $mediaRepresentationPart->width;
374
		if($w == 0 || $h == 0){
375
			$image_uri = str_replace(' ','%20',$mediaRepresentationPart->uri); //take url and replace spaces
376
			$imageDimensions = getimagesize_remote($image_uri);
377
			if(!$imageDimensions){
378
				return '<div>'.t('Image unavailable, uri: ').$mediaRepresentationPart->uri.'</div>';
379
			}
380
			$w = $imageDimensions[0];
381
			$h = $imageDimensions[1];
382
		}
383
		$margins = '0 0 0 0';
384
		$ratio = $w / $h;
385
		if($ratio > 1){
386
			$displayHeight = round($maxExtend / $ratio);
387
			$displayWidth = $maxExtend;
388
			$m = round(($maxExtend - $displayHeight) / 2);
389
			$margins = 'margin:'.$m.'px 0 '.$m.'px 0;';
390
		} else {
391
			$displayHeight = $maxExtend;
392
			$displayWidth = round($maxExtend * $ratio);
393
			$m = round(($maxExtend - $displayWidth) / 2);
394
			$margins = 'margin:0 '.$m.'px 0 '.$m.'px;';
395
		}
396

    
397
		// turn attributes array into string
398
		$attrStr = ' ';
399
		//$attributes['title'] = 'h:'.$h.', w:'.$w.',ratio:'.$ratio;
400
		if(is_array($attributes)){
401
			foreach($attributes as $name=>$value){
402
				$attrStr .= $name.'="'.$value.'" ';
403
			}
404
		}
405

    
406
		//return  '<img src="'."http://wp5.e-taxonomy.eu/dataportal/cichorieae/media/photos/Lapsana_communis_A_01.jpg".'" width="'.$maxExtend.'" height="'.$maxExtend.'" />';
407
		if($addPassePartout){
408
			$out .= '<div class="image-passe-partout" style="width:'.$maxExtend.'px; height:'.$maxExtend.'px;">';
409
		} else {
410
			// do not add margins if no pass partout is shown
411
			$margins = '';
412
		}
413
		$out .= '<img src="'.$mediaRepresentationPart->uri.'" width="'.$displayWidth.'" height="'.$displayHeight.'" style="'.$margins.'"'.$attrStr.' />';
414

    
415
		if($addPassePartout){
416
			$out .= '</div>';
417
		}
418
		return $out;
419
	}
420

    
421
}
422

    
423
function theme_cdm_media_gallerie_application($mediaRepresentationPart, $maxExtend, $addPassePartout = FALSE, $attributes = null){
424

    
425
	if(isset($mediaRepresentationPart)){
426

    
427
		if($addPassePartout){
428
			$out .= '<div class="image-passe-partout" style="width:'.$maxExtend.'px; height:'.$maxExtend.'px;">';
429
		} else {
430
			// do not add margins if no pass partout is shown
431
			$margins = '';
432
		}
433
		$out .= '<div class="appication">Web Application</div>';
434

    
435
		if($addPassePartout){
436
			$out .= '</div>';
437
		}
438
		return $out;
439
	}
440

    
441
}
442

    
443
function theme_cdm_media_gallerie_text($mediaRepresentationPart, $maxExtend, $addPassePartout = FALSE, $attributes = null){
444

    
445
	if(isset($mediaRepresentationPart)){
446

    
447
		if($addPassePartout){
448
			$out .= '<div class="image-passe-partout" style="width:'.$maxExtend.'px; height:'.$maxExtend.'px;">';
449
		} else {
450
			// do not add margins if no pass partout is shown
451
			$margins = '';
452
		}
453
		$out .= '<div class="appication">Web Application</div>';
454

    
455
		if($addPassePartout){
456
			$out .= '</div>';
457
		}
458
		return $out;
459
	}
460

    
461
}
462

    
463
function theme_cdm_openlayers_image($mediaRepresentationPart, $maxExtend){
464

    
465
	// see http://trac.openlayers.org/wiki/UsingCustomTiles#UsingTilesWithoutaProjection
466
	// and http://trac.openlayers.org/wiki/SettingZoomLevels
467

    
468
	drupal_add_js(drupal_get_path('module', 'cdm_dataportal').'/js/OpenLayers/OpenLayers.js', 'core', 'header');
469

    
470
	//TODO megre code below with code from theme_cdm_media_gallerie_image
471
	//var_dump("MEDIA URI: " . $mediaRepresentationPart->uri);
472
	//TODO merge code below with code from theme_cdm_media_gallerie_image
473
	$w = $mediaRepresentationPart->width;
474
	$h = $mediaRepresentationPart->height;
475

    
476
	if($w == 0 || $h == 0){
477
		$image_uri = str_replace(' ','%20',$mediaRepresentationPart->uri); //take url and replace spaces
478
		$imageDimensions = getimagesize_remote($image_uri);
479
		if(!$imageDimensions){
480
			return '<div>'.t('Image unavailable, uri:').$mediaRepresentationPart->uri.'</div>';
481
		}
482
		$w = $imageDimensions[0];
483
		$h = $imageDimensions[1];
484
	}
485

    
486
	// calculate  maxResolution (default is 360 deg / 256 px) and the bounds
487
	if($w > $h){
488
		$lat = 90;
489
		$lon = 90 * ($h / $w);
490
		$maxRes = $w / $maxExtend;
491
	} else {
492
		$lat = 90 * ($w / $h);
493
		$lon = 90;
494
		$maxRes =  $h / $maxExtend ;
495
	}
496

    
497
	$maxRes *= 1;
498
	drupal_add_js('
499
 var map;
500

    
501
 var imageLayerOptions={
502
     maxResolution: '.$maxRes.',
503
     maxExtent: new OpenLayers.Bounds(0, 0, '.$w.', '.$h.')
504
  };
505
  var mapOptions={
506
      controls:
507
       [
508
         new OpenLayers.Control.PanZoom(),
509
         new OpenLayers.Control.Navigation({zoomWheelEnabled: false, handleRightClicks:true, zoomBoxKeyMask: OpenLayers.Handler.MOD_CTRL})
510
       ],
511
     restrictedExtent:  new OpenLayers.Bounds(0, 0, '.$w.', '.$h.')
512
  };
513

    
514
 var graphic = new OpenLayers.Layer.Image(
515
          \'Image Title\',
516
          \''.$mediaRepresentationPart->uri.'\',
517
          new OpenLayers.Bounds(0, 0, '.$w.', '.$h.'),
518
          new OpenLayers.Size('.$w.', '.$h.'),
519
          imageLayerOptions
520
          );
521

    
522
 function init() {
523
   map = new OpenLayers.Map(\'openlayers_image\', mapOptions);
524
   map.addLayers([graphic]);
525
   map.setCenter(new OpenLayers.LonLat(0, 0), 1);
526
   map.zoomToMaxExtent();
527
 }
528

    
529
$(document).ready(function(){
530
  init();
531

    
532
});'
533
	, 'inline');
534
	$out = '<div id="openlayers_image" class="image_viewer" style="width: '.$maxExtend.'px; height:'.($maxExtend).'px"></div>';
535
	return $out;
536

    
537
}
538

    
539

    
540
function theme_cdm_preferredImage($media, $defaultRepresentationPart, $imageMaxExtend, $parameters = ''){
541

    
542
	if(isset($media[0])){
543
		$representationPart = $media[0]->representations[0]->parts[0];
544
		if($parameters){
545
			$representationPart->uri.$parameters;
546
		}
547
	} else {
548
		$representationPart = $defaultRepresentationPart;
549
	}
550

    
551
	//$widthAndHeight = ($imageWidth ? ' width="'.$imageWidth : '').($imageHeight ? '" height="'.$imageHeight : '');
552
	//  $imageUri = $preferredMedia ? $preferredMedia->representations[0]->parts[0]->uri . $parameters : $defaultImage;
553
	$attributes = array('alt'=>($preferredMedia ? $preferredMedia->representations[0]->parts[0]->uri : "no image available"));
554
	$out .= theme('cdm_media_gallerie_image', $representationPart, $imageMaxExtend, false, $attributes);
555
	// $out = '<img class="left" '.$widthAndHeight.' " src="'.$imageUri.'" alt="'.$altText.'" />';
556
	return $out;
557
}
(3-3/8)