Skip to content

Instantly share code, notes, and snippets.

@peterchester
Created June 25, 2014 23:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterchester/7504965aae068513b8c8 to your computer and use it in GitHub Desktop.
Save peterchester/7504965aae068513b8c8 to your computer and use it in GitHub Desktop.
MvcImageResize - Mat's Fabulous WordPress Image Resizer
<?php
/*
Plugin Name: Mat's Fabulous Image Resizer
Description: Peter has hacked Mat's image resizer a bit to make it a stand alone plugin for the sake of team testing & inspection.
*/
/**
* Manage Image resizing on the fly to prevent a bunch of uneeded image sizes for every image uploaded
* Includes support for the Wp Smush.it plugin and will run the smush on all image sizes when generating the thumbnails. This also allow for smushing image larger than 1mb when
* using cropped sizes less than 1MB
*
* @author Mat Lipe <mat@matlipe.com>
* @uses Pretty much automatic - use standard WP add_image_size() and this will pick it up
* @May be tapped in using the pulbic methods as well - however probably not neccessary
*
* @since 11.10.13
*/
class MvcImageResize {
protected $_image_sizes = array(); //Keeps track of all theme and plugins image sizes
/**
* @since 9.13.13
*/
function __construct() {
// convert other add_image_sizes from other plugin, to the attribute of the class
add_action( 'init', array( $this, 'add_other_image_sizes' ) );
// use this class to resize on the fly instead of making a copy of each image
add_filter( 'image_downsize', array( $this, 'convert_image_downsize' ), 10, 3 );
}
/**
* Populate image sizes
*
* @since 9.13.13
*/
public function add_image_size( $name, $width, $height, $crop = false ) {
$this->_image_sizes[$name] = array( 'width' => absint( $width ), 'height' => absint( $height ), 'crop' => (bool) $crop );
}
/**
* Convert other add_image_sizes from other plugin, to the attribute of the class
*
* @since 9.13.13
*/
public function add_other_image_sizes() {
global $_wp_additional_image_sizes;
if ( empty( $_wp_additional_image_sizes ) ) return;
foreach ( $_wp_additional_image_sizes as $size => $the_ ) {
if ( isset( $this->_image_sizes[$size] ) ) continue;
$this->add_image_size( $size, $the_['width'], $the_['height'], $the_['crop'] );
unset( $_wp_additional_image_sizes[$size] );
}
}
/**
* Get image
*
* @param array() $args = array(
* 'id' => null, // the thumbnail ID
* 'post_id' => null, // the thumbnail ID
* 'src' => '',
* 'alt' => '',
* 'class' => '',
* 'title' => '',
* 'size' => '',
* 'width' => null,
* 'height' => null,
* 'crop' => false,
* 'image_scan' => false, // set if get the image from the first image of the post
* 'output' => 'img', // how print: 'a', with anchor; 'img' without anchor; 'url' only url; 'array' array width 'url', 'width' and 'height'
* 'link' => '', // the link of <a> tag. If empty, get from original image url
* 'link_class' => '', // the class of <a> tag
* 'link_title' => '', // the title of <a> tag. If empty, get it from "title" attribute.
* );
* @param bool $echo
* @return array|null|string
*
* @since 9.13.13
*/
public function image( $args = array(), $echo = true ) {
$defaults = array(
'id' => null, // the thumbnail ID
'post_id' => null, // the thumbnail ID
'src' => '',
'alt' => '',
'class' => '',
'title' => '',
'size' => '',
'width' => null,
'height' => null,
'crop' => false,
'image_scan' => false, // set if get the image from the first image of the post
'output' => 'img', // how print: 'a', with anchor; 'img' without anchor; 'url' only url; 'array' array width 'url', 'width' and 'height'
'link' => '', // the link of <a> tag. If empty, get from original image url
'link_class' => '', // the class of <a> tag
'link_title' => '', // the title of <a> tag. If empty, get it from "title" attribute.
);
extract( wp_parse_args( $args, $defaults ) );
/* SET VARS FOR OUTPUT */
// from esplicit thumbnail ID
if ( ! empty( $id ) ) {
$image_id = $id;
$image_url = wp_get_attachment_url( $id );
// or from SRC
} elseif ( ! empty( $post_id ) ) {
$image_id = get_post_thumbnail_id( $post_id );
$image_url = wp_get_attachment_url( $image_id );
// or from SRC
} elseif ( ! empty( $src ) ) {
$image_id = null;
$image_url = esc_url( $src );
// or the post thumbnail
} elseif ( has_post_thumbnail() ) {
$image_id = get_post_thumbnail_id();
$image_url = wp_get_attachment_url( $image_id );
// get the first image of the post
} elseif ( $image_scan ) {
$image_id = null;
$image_url = $this->getFirstContentImage( $post_id );
// if is an attachment
} elseif ( is_attachment() ) {
global $post;
$image_id = $post->ID;
$image_url = wp_get_attachment_url( $image_id );
} else {
return null;
}
// return null, if any image is defined
if ( empty( $image_url ) && empty( $image_id ) ) return;
// save original image url for the <a> tag
$full_image_url = $image_url;
// get the post attachment
if ( ! empty( $image_id ) ) $attachment = get_post( $image_id );
// get size from add_image_size
if ( ! empty( $size ) ) {
global $_wp_additional_image_sizes, $content_width;
// if is array, put width and height indivudually
if ( is_array($size) ) {
$width = $size[0];
$height = $size[1];
} elseif ( isset( $this->_image_sizes[$size] ) ) {
$width = $this->_image_sizes[$size]['width'];
$height = $this->_image_sizes[$size]['height'];
$crop = $this->_image_sizes[$size]['crop'];
} elseif ( isset( $_wp_additional_image_sizes[$size] ) ) {
$width = $_wp_additional_image_sizes[$size]['width'];
$height = $_wp_additional_image_sizes[$size]['height'];
$crop = $_wp_additional_image_sizes[$size]['crop'];
// standard sizes of wordpress
// thumbnail
} elseif ( $size == 'thumb' || $size == 'thumbnail' ) {
$width = intval(get_option('thumbnail_size_w'));
$height = intval(get_option('thumbnail_size_h'));
// last chance thumbnail size defaults
if ( !$width && !$height ) {
$width = 128;
$height = 96;
}
$crop = (bool) get_option('thumbnail_crop');
// medium
} elseif ( $size == 'medium' ) {
$width = intval(get_option('medium_size_w'));
$height = intval(get_option('medium_size_h'));
// if no width is set, default to the theme content width if available
// large
} elseif ( $size == 'large' ) {
// We're inserting a large size image into the editor. If it's a really
// big image we'll scale it down to fit reasonably within the editor
// itself, and within the theme's content width if it's known. The user
// can resize it in the editor if they wish.
$width = intval(get_option('large_size_w'));
$height = intval(get_option('large_size_h'));
if ( intval($content_width) > 0 )
$width = min( intval($content_width), $width );
}
}
// maybe need resize
if ( !empty( $width ) || !empty( $height ) ) {
$image = $this->resize( $image_id, $image_url, $width, $height, $crop );
$image_url = $image['url'];
$width = $image['width'];
$height = $image['height'];
// no need resize
} else {}
/* BEGIN OUTPUT */
$attr = array();
// return null, if there isn't $image_url
if ( empty( $image_url ) ) return;
// if return only url
if ( $output == 'url' ) {
if ( $echo ) echo $image_url;
return $image_url;
// if return array
} elseif ( $output == 'array' ) {
return array( $image_url, $width, $height );
}
if ( ! empty( $image_id ) ) {
$size = empty( $size ) ? $size = array( $width, $height ) : $size;
if ( $output != 'a' ) $class .= ' mvc-resized-image';
$html_image = wp_get_attachment_image( $image_id, $size, false, array(
'class' => trim( "$class" . ( ! is_array( $size ) && ! empty( $size ) ? " attachment-$size" : '' ) ),
'alt' => empty( $alt ) ? trim(strip_tags( get_post_meta($image_id, '_wp_attachment_image_alt', true) )) : $alt,
'title' => empty( $title ) ? $attachment->post_title : $title,
) );
} else {
$html_image = rtrim("<img");
if ( $output != 'a' ) $class .= ' mvc-resized-image';
if ( ! is_array( $size ) && ! empty( $size ) ) $class .= " attachment-$size";
$attr = array(
'src' => $image_url,
'alt' => $alt,
'title' => $title,
'class' => trim($class),
'width' => $width,
'height' => $height
);
foreach ( $attr as $name => $value ) {
if ( ! empty( $value ) ) $html_image .= " $name=" . '"' . $value . '"';
}
$html_image .= ' />';
}
// return only image
if ( $output == 'img' ) {
if ( $echo ) echo $html_image;
return $html_image;
// return the image wrapper in <a> tag
} elseif ( $output == 'a' ) {
$html_link = rtrim("<a");
$link_class .= ' mvc-resized-image';
$attr = array(
'href' => empty( $link ) ? $full_image_url : $link,
'title' => empty( $link_title ) ? $title : $link_title,
'class' => trim($link_class)
);
foreach ( $attr as $name => $value ) {
if ( ! empty( $value ) ) $html_link .= " $name=" . '"' . $value . '"';
}
$html_link .= '>' . $html_image . '</a>';
if ( $echo ) echo $html_link;
return $html_link;
}
}
/**
* Resize images dynamically using wp built in functions
* Will also run the images through smush.it if available
*
* @param int $attach_id
* @param string $img_url
* @param int $width
* @param int $height
* @param bool $crop
*
* @since 11.10.13
*
* @return array
*/
protected function resize( $attach_id = null, $img_url = null, $width, $height, $crop = false ) {
// Cast $width and $height to integer
$width = intval( $width );
$height = intval( $height );
// this is an attachment, so we have the ID
if ( $attach_id ) {
$image_src = wp_get_attachment_image_src( $attach_id, 'full' );
$file_path = get_attached_file( $attach_id );
// this is not an attachment, let's use the image url
} else if ( $img_url ) {
$uploads_dir = wp_upload_dir();
if ( strpos( $img_url, $uploads_dir['baseurl'] ) === false ) {
$file_path = parse_url( esc_url( $img_url ) );
$file_path = $_SERVER['DOCUMENT_ROOT'] . $file_path['path'];
} else {
$file_path = str_replace( $uploads_dir['baseurl'], $uploads_dir['basedir'], $img_url );
}
$orig_size = getimagesize( $file_path );
$image_src[0] = $img_url;
$image_src[1] = $orig_size[0];
$image_src[2] = $orig_size[1];
}
$file_info = pathinfo( $file_path );
// check if file exists
if ( !isset( $file_info['dirname'] ) && !isset( $file_info['filename'] ) && !isset( $file_info['extension'] ) )
return;
$base_file = $file_info['dirname'].'/'.$file_info['filename'].'.'.$file_info['extension'];
if ( !file_exists($base_file) )
return;
$extension = '.'. $file_info['extension'];
// the image path without the extension
$no_ext_path = $file_info['dirname'].'/'.$file_info['filename'];
$cropped_img_path = $no_ext_path.'-'.$width.'x'.$height.$extension;
// checking if the file size is larger than the target size
// if it is smaller or the same size, stop right here and return
if ( $image_src[1] > $width || $image_src[2] > $height ) {
// the file is larger, check if the resized version already exists (for $crop = true but will also work for $crop = false if the sizes match)
if ( file_exists( $cropped_img_path ) ) {
$cropped_img_url = str_replace( basename( $image_src[0] ), basename( $cropped_img_path ), $image_src[0] );
$image = array (
'url' => $cropped_img_url,
'width' => $width,
'height' => $height
);
return $image;
}
// $crop = false or no height set
if ( $crop == false OR !$height ) {
// calculate the size proportionaly
$proportional_size = wp_constrain_dimensions( $image_src[1], $image_src[2], $width, $height );
$resized_img_path = $no_ext_path.'-'.$proportional_size[0].'x'.$proportional_size[1].$extension;
// checking if the file already exists
if ( file_exists( $resized_img_path ) ) {
$resized_img_url = str_replace( basename( $image_src[0] ), basename( $resized_img_path ), $image_src[0] );
$image = array (
'url' => $resized_img_url,
'width' => $proportional_size[0],
'height' => $proportional_size[1]
);
return $image;
}
}
// check if image width is smaller than set width
$img_size = getimagesize( $file_path );
if ( $img_size[0] <= $width ) $width = $img_size[0];
// Check if GD Library installed
if ( ! function_exists ( 'imagecreatetruecolor' ) ) {
echo 'GD Library Error: imagecreatetruecolor does not exist - please contact your webhost and ask them to install the GD library';
return;
}
// no cache files - let's finally resize it
if ( function_exists( 'wp_get_image_editor' ) ) {
$image = wp_get_image_editor( $file_path );
if ( ! is_wp_error( $image ) ) {
$image->resize( $width, $height, $crop );
$save_data = $image->save();
$new_img_path = ( isset( $save_data['path'] ) && !is_wp_error( $save_data['path'] ) ) ? $save_data['path'] : $file_path;
}
} else {
$new_img_path = image_resize( $file_path, $width, $height, $crop );
}
$new_img_size = getimagesize( $new_img_path );
$new_img = str_replace( basename( $image_src[0] ), basename( $new_img_path ), $image_src[0] );
// resized output
$image = array (
'url' => $new_img,
'width' => $new_img_size[0],
'height' => $new_img_size[1]
);
//If using Wp Smushit
if( class_exists('WpSmushit') ){
global $WpSmushit;
if( filesize( $new_img_path ) < WP_SMUSHIT_MAX_BYTES ){
$WpSmushit->do_smushit($new_img_path, $new_img);
}
}
return $image;
}
// default output - without resizing
$image = array (
'url' => $image_src[0],
'width' => $image_src[1],
'height' => $image_src[2]
);
return $image;
}
/**
* Uses this class to resize an image instead of default wp
*
* @uses added to the image_downsize filter by self::__construct()
* @since 9.13.13
*
*/
public function convert_image_downsize( $out, $id, $size ) {
if ( $size == 'full' ) return $out;
$new_image = $this->image( array(
'id' => $id,
'size' => $size,
'output' => 'array'
) );
if ( empty( $new_image ) ) return $out;
// is_intermediate
$new_image[] = true;
return $new_image;
}
}
new MvcImageResize();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment