3 // functions for media display
5 // scale down the default size of an image so it's a better fit for the editor and theme
6 function image_constrain_size_for_editor($width, $height, $size = 'medium') {
8 if ( is_array($size) ) {
10 $max_height = $size[1];
12 elseif ( $size == 'thumb' || $size == 'thumbnail' ) {
13 $max_width = intval(get_option('thumbnail_size_w'));
14 $max_height = intval(get_option('thumbnail_size_h'));
15 // last chance thumbnail size defaults
16 if ( !$max_width && !$max_height ) {
21 elseif ( $size == 'medium' ) {
22 $max_width = intval(get_option('medium_size_w'));
23 $max_height = intval(get_option('medium_size_h'));
24 // if no width is set, default to the theme content width if available
26 else { // $size == 'full'
27 // we're inserting a full size image into the editor. if it's a really big image we'll scale it down to fit reasonably
28 // within the editor itself, and within the theme's content width if it's known. the user can resize it in the editor
30 if ( !empty($GLOBALS['content_width']) ) {
31 $max_width = $GLOBALS['content_width'];
37 list( $max_width, $max_height ) = apply_filters( 'editor_max_image_size', array( $max_width, $max_height ), $size );
39 return wp_constrain_dimensions( $width, $height, $max_width, $max_height );
42 // return a width/height string for use in an <img /> tag. Empty values will be omitted.
43 function image_hwstring($width, $height) {
46 $out .= 'width="'.intval($width).'" ';
48 $out .= 'height="'.intval($height).'" ';
52 // Scale an image to fit a particular size (such as 'thumb' or 'medium'), and return an image URL, height and width.
53 // The URL might be the original image, or it might be a resized version. This function won't create a new resized copy, it will just return an already resized one if it exists.
54 // returns an array($url, $width, $height)
55 function image_downsize($id, $size = 'medium') {
57 if ( !wp_attachment_is_image($id) )
60 $img_url = wp_get_attachment_url($id);
61 $meta = wp_get_attachment_metadata($id);
64 // plugins can use this to provide resize services
65 if ( $out = apply_filters('image_downsize', false, $id, $size) )
68 // try for a new style intermediate size
69 if ( $intermediate = image_get_intermediate_size($id, $size) ) {
70 $img_url = str_replace(basename($img_url), $intermediate['file'], $img_url);
71 $width = $intermediate['width'];
72 $height = $intermediate['height'];
74 elseif ( $size == 'thumbnail' ) {
75 // fall back to the old thumbnail
76 if ( $thumb_file = wp_get_attachment_thumb_file() && $info = getimagesize($thumb_file) ) {
77 $img_url = str_replace(basename($img_url), basename($thumb_file), $img_url);
82 if ( !$width && !$height && isset($meta['width'], $meta['height']) ) {
83 // any other type: use the real image and constrain it
84 list( $width, $height ) = image_constrain_size_for_editor( $meta['width'], $meta['height'], $size );
88 return array( $img_url, $width, $height );
93 // return an <img src /> tag for the given image attachment, scaling it down if requested
94 function get_image_tag($id, $alt, $title, $align, $size='medium') {
96 list( $img_src, $width, $height ) = image_downsize($id, $size);
97 $hwstring = image_hwstring($width, $height);
99 $html = '<img src="'.attribute_escape($img_src).'" alt="'.attribute_escape($alt).'" title="'.attribute_escape($title).'" '.$hwstring.'class="align'.attribute_escape($align).' size-'.attribute_escape($size).' wp-image-'.$id.'" />';
102 $html = apply_filters( 'image_send_to_editor', $html, $id, $alt, $title, $align, $url, $size );
107 // same as wp_shrink_dimensions, except the max parameters are optional.
108 // if either width or height are empty, no constraint is applied on that dimension.
109 function wp_constrain_dimensions( $current_width, $current_height, $max_width=0, $max_height=0 ) {
110 if ( !$max_width and !$max_height )
111 return array( $current_width, $current_height );
113 $width_ratio = $height_ratio = 1.0;
115 if ( $max_width > 0 && $current_width > $max_width )
116 $width_ratio = $max_width / $current_width;
118 if ( $max_height > 0 && $current_height > $max_height )
119 $height_ratio = $max_height / $current_height;
121 // the smaller ratio is the one we need to fit it to the constraining box
122 $ratio = min( $width_ratio, $height_ratio );
124 return array( intval($current_width * $ratio), intval($current_height * $ratio) );
127 // calculate dimensions and coordinates for a resized image that fits within a specified width and height
128 // if $crop is true, the largest matching central portion of the image will be cropped out and resized to the required size
129 function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop=false) {
131 if ($orig_w <= 0 || $orig_h <= 0)
133 // at least one of dest_w or dest_h must be specific
134 if ($dest_w <= 0 && $dest_h <= 0)
138 // crop the largest possible portion of the original image that we can size to $dest_w x $dest_h
139 $aspect_ratio = $orig_w / $orig_h;
140 $new_w = min($dest_w, $orig_w);
141 $new_h = min($dest_h, $orig_h);
143 $new_w = intval($new_h * $aspect_ratio);
146 $new_h = intval($new_w / $aspect_ratio);
149 $size_ratio = max($new_w / $orig_w, $new_h / $orig_h);
151 $crop_w = ceil($new_w / $size_ratio);
152 $crop_h = ceil($new_h / $size_ratio);
154 $s_x = floor(($orig_w - $crop_w)/2);
155 $s_y = floor(($orig_h - $crop_h)/2);
158 // don't crop, just resize using $dest_w x $dest_h as a maximum bounding box
165 list( $new_w, $new_h ) = wp_constrain_dimensions( $orig_w, $orig_h, $dest_w, $dest_h );
168 // if the resulting image would be the same size or larger we don't want to resize it
169 if ($new_w >= $orig_w && $new_h >= $orig_h)
172 // the return array matches the parameters to imagecopyresampled()
173 // int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h
174 return array(0, 0, $s_x, $s_y, $new_w, $new_h, $crop_w, $crop_h);
178 // Scale down an image to fit a particular size and save a new copy of the image
179 function image_resize( $file, $max_w, $max_h, $crop=false, $suffix=null, $dest_path=null, $jpeg_quality=90) {
181 $image = wp_load_image( $file );
182 if ( !is_resource( $image ) )
183 return new WP_Error('error_loading_image', $image);
185 list($orig_w, $orig_h, $orig_type) = getimagesize( $file );
186 $dims = image_resize_dimensions($orig_w, $orig_h, $max_w, $max_h, $crop);
189 list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $dims;
191 $newimage = imagecreatetruecolor( $dst_w, $dst_h);
193 // preserve PNG transparency
194 if ( IMAGETYPE_PNG == $orig_type && function_exists( 'imagealphablending' ) && function_exists( 'imagesavealpha' ) ) {
195 imagealphablending( $newimage, false);
196 imagesavealpha( $newimage, true);
199 imagecopyresampled( $newimage, $image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
201 // we don't need the original in memory anymore
202 imagedestroy( $image );
204 // $suffix will be appended to the destination filename, just before the extension
206 $suffix = "{$dst_w}x{$dst_h}";
208 $info = pathinfo($file);
209 $dir = $info['dirname'];
210 $ext = $info['extension'];
211 $name = basename($file, ".{$ext}");
212 if ( !is_null($dest_path) and $_dest_path = realpath($dest_path) )
214 $destfilename = "{$dir}/{$name}-{$suffix}.{$ext}";
216 if ( $orig_type == IMAGETYPE_GIF ) {
217 if (!imagegif( $newimage, $destfilename ) )
218 return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
220 elseif ( $orig_type == IMAGETYPE_PNG ) {
221 if (!imagepng( $newimage, $destfilename ) )
222 return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
225 // all other formats are converted to jpg
226 $destfilename = "{$dir}/{$name}-{$suffix}.jpg";
227 if (!imagejpeg( $newimage, $destfilename, apply_filters( 'jpeg_quality', $jpeg_quality ) ) )
228 return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
231 imagedestroy( $newimage );
233 // Set correct file permissions
234 $stat = stat( dirname( $destfilename ));
235 $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
236 @ chmod( $destfilename, $perms );
238 return $destfilename;
241 // resize an image to make a thumbnail or intermediate size, and return metadata describing the new copy
242 // returns false if no image was created
243 function image_make_intermediate_size($file, $width, $height, $crop=false) {
244 if ( $width || $height ) {
245 $resized_file = image_resize($file, $width, $height, $crop);
246 if ( !is_wp_error($resized_file) && $resized_file && $info = getimagesize($resized_file) ) {
247 $resized_file = apply_filters('image_make_intermediate_size', $resized_file);
249 'file' => basename( $resized_file ),
251 'height' => $info[1],
258 function image_get_intermediate_size($post_id, $size='thumbnail') {
259 if ( !$imagedata = wp_get_attachment_metadata( $post_id ) )
262 // get the best one for a specified set of dimensions
263 if ( is_array($size) && !empty($imagedata['sizes']) ) {
264 foreach ( $imagedata['sizes'] as $_size => $data ) {
265 // already cropped to width or height; so use this size
266 if ( ( $data['width'] == $size[0] && $data['height'] <= $size[1] ) || ( $data['height'] == $size[1] && $data['width'] <= $size[0] ) ) {
267 $file = $data['file'];
268 list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
269 return compact( 'file', 'width', 'height' );
271 // add to lookup table: area => size
272 $areas[$data['width'] * $data['height']] = $_size;
274 if ( !$size || !empty($areas) ) {
275 // find for the smallest image not smaller than the desired size
277 foreach ( $areas as $_size ) {
278 $data = $imagedata['sizes'][$_size];
279 if ( $data['width'] >= $size[0] || $data['height'] >= $size[1] ) {
280 $file = $data['file'];
281 list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
282 return compact( 'file', 'width', 'height' );
288 if ( is_array($size) || empty($size) || empty($imagedata['sizes'][$size]) )
291 $data = $imagedata['sizes'][$size];
292 // include the full filesystem path of the intermediate file
293 if ( empty($data['path']) && !empty($data['file']) ) {
294 $file_url = wp_get_attachment_url($post_id);
295 $data['path'] = path_join( dirname($imagedata['file']), $data['file'] );
296 $data['url'] = path_join( dirname($file_url), $data['file'] );
301 // get an image to represent an attachment - a mime icon for files, thumbnail or intermediate size for images
302 // returns an array (url, width, height), or false if no image is available
303 function wp_get_attachment_image_src($attachment_id, $size='thumbnail', $icon = false) {
305 // get a thumbnail or intermediate image if there is one
306 if ( $image = image_downsize($attachment_id, $size) )
309 if ( $icon && $src = wp_mime_type_icon($attachment_id) ) {
310 $icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/crystal' );
311 $src_file = $icon_dir . '/' . basename($src);
312 @list($width, $height) = getimagesize($src_file);
314 if ( $src && $width && $height )
315 return array( $src, $width, $height );
319 // as per wp_get_attachment_image_src, but returns an <img> tag
320 function wp_get_attachment_image($attachment_id, $size='thumbnail', $icon = false) {
323 $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
325 list($src, $width, $height) = $image;
326 $hwstring = image_hwstring($width, $height);
327 if ( is_array($size) )
328 $size = join('x', $size);
329 $html = '<img src="'.attribute_escape($src).'" '.$hwstring.'class="attachment-'.attribute_escape($size).'" alt="" />';
335 add_shortcode('gallery', 'gallery_shortcode');
337 function gallery_shortcode($attr) {
340 // Allow plugins/themes to override the default gallery template.
341 $output = apply_filters('post_gallery', '', $attr);
345 // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
346 if ( isset( $attr['orderby'] ) ) {
347 $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
348 if ( !$attr['orderby'] )
349 unset( $attr['orderby'] );
352 extract(shortcode_atts(array(
353 'orderby' => 'menu_order ASC, ID ASC',
357 'captiontag' => 'dd',
359 'size' => 'thumbnail',
363 $attachments = get_children("post_parent=$id&post_type=attachment&post_mime_type=image&orderby={$orderby}");
365 if ( empty($attachments) )
370 foreach ( $attachments as $id => $attachment )
371 $output .= wp_get_attachment_link($id, $size, true) . "\n";
375 $listtag = tag_escape($listtag);
376 $itemtag = tag_escape($itemtag);
377 $captiontag = tag_escape($captiontag);
378 $columns = intval($columns);
379 $itemwidth = $columns > 0 ? floor(100/$columns) : 100;
381 $output = apply_filters('gallery_style', "
382 <style type='text/css'>
390 width: {$itemwidth}%; }
392 border: 2px solid #cfcfcf;
398 <!-- see gallery_shortcode() in wp-includes/media.php -->
399 <div class='gallery'>");
401 foreach ( $attachments as $id => $attachment ) {
402 $link = wp_get_attachment_link($id, $size, true);
403 $output .= "<{$itemtag} class='gallery-item'>";
405 <{$icontag} class='gallery-icon'>
408 if ( $captiontag && trim($attachment->post_excerpt) ) {
410 <{$captiontag} class='gallery-caption'>
411 {$attachment->post_excerpt}
414 $output .= "</{$itemtag}>";
415 if ( $columns > 0 && ++$i % $columns == 0 )
416 $output .= '<br style="clear: both" />';
420 <br style='clear: both;' />
426 function previous_image_link() {
427 adjacent_image_link(true);
430 function next_image_link() {
431 adjacent_image_link(false);
434 function adjacent_image_link($prev = true) {
436 $post = get_post($post);
437 $attachments = array_values(get_children("post_parent=$post->post_parent&post_type=attachment&post_mime_type=image&orderby=menu_order ASC, ID ASC"));
439 foreach ( $attachments as $k => $attachment )
440 if ( $attachment->ID == $post->ID )
443 $k = $prev ? $k - 1 : $k + 1;
445 if ( isset($attachments[$k]) )
446 echo wp_get_attachment_link($attachments[$k]->ID, 'thumbnail', true);
449 function get_attachment_taxonomies($attachment) {
450 if ( is_int( $attachment ) )
451 $attachment = get_post($attachment);
452 else if ( is_array($attachment) )
453 $attachment = (object) $attachment;
455 if ( ! is_object($attachment) )
458 $filename = basename($attachment->guid);
460 $objects = array('attachment');
462 if ( false !== strpos($filename, '.') )
463 $objects[] = 'attachment:' . substr($filename, strrpos($filename, '.') + 1);
464 if ( !empty($attachment->post_mime_type) ) {
465 $objects[] = 'attachment:' . $attachment->post_mime_type;
466 if ( false !== strpos($attachment->post_mime_type, '/') )
467 foreach ( explode('/', $attachment->post_mime_type) as $token )
468 if ( !empty($token) )
469 $objects[] = "attachment:$token";
472 $taxonomies = array();
473 foreach ( $objects as $object )
474 if ( $taxes = get_object_taxonomies($object) )
475 $taxonomies = array_merge($taxonomies, $taxes);
477 return array_unique($taxonomies);