Created
February 19, 2018 10:18
-
-
Save liviucerchez/136b3bd59819527ebfda306d44c4626a to your computer and use it in GitHub Desktop.
custom image resize
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Resizes an image and returns the resized URL. Uses native WordPress functionality. | |
* | |
* The function supports GD Library and ImageMagick. WordPress will pick whichever is most appropriate. | |
* If none of the supported libraries are available, the function will return the original image url. | |
* | |
* Images are saved to the WordPress uploads directory, just like images uploaded through the Media Library. | |
* | |
* Supports WordPress 3.5 and above. | |
* | |
*/ | |
add_action('delete_attachment', 'cerchez_delete_resized_images'); | |
function cerchez_image_resize($url, $width=null, $height=null, $crop=true, $align='c', $retina=false) { | |
global $wpdb; | |
$args = func_get_args(); | |
$common = cerchez_common_info($args); | |
if (is_array($common)) { | |
extract($common); | |
} else { | |
return $common; | |
} | |
if ( ! file_exists($dest_file_name)) { | |
// We only want to resize Media Library images, so we can be sure they get deleted correctly when appropriate | |
$query = $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE guid='%s'", $url); | |
$get_attachment = $wpdb->get_results($query); | |
$editor = wp_get_image_editor($file_path); | |
if (is_wp_error($editor)) { | |
if (is_user_logged_in()) print_r($editor); | |
return null; | |
} | |
if ($crop) { | |
$src_x = $src_y = 0; | |
$src_w = $orig_width; | |
$src_h = $orig_height; | |
$cmp_x = $orig_width / $dest_width; | |
$cmp_y = $orig_height / $dest_height; | |
if ($cmp_x > $cmp_y) { | |
$src_w = round ($orig_width / $cmp_x * $cmp_y); | |
$src_x = round (($orig_width - ($orig_width / $cmp_x * $cmp_y)) / 2); | |
} else if ($cmp_y > $cmp_x) { | |
$src_h = round ($orig_height / $cmp_y * $cmp_x); | |
$src_y = round (($orig_height - ($orig_height / $cmp_y * $cmp_x)) / 2); | |
} | |
if ($align && $align != 'c') { | |
if (strpos ($align, 't') !== false) { | |
$src_y = 0; | |
} | |
if (strpos ($align, 'b') !== false) { | |
$src_y = $orig_height - $src_h; | |
} | |
if (strpos ($align, 'l') !== false) { | |
$src_x = 0; | |
} | |
if (strpos ($align, 'r') !== false) { | |
$src_x = $orig_width - $src_w; | |
} | |
} | |
$editor->crop($src_x, $src_y, $src_w, $src_h, $dest_width, $dest_height); | |
} else { | |
$editor->resize($dest_width, $dest_height); | |
} | |
$saved = $editor->save($dest_file_name); | |
if (is_wp_error($saved)) { | |
if (is_user_logged_in()) { | |
print_r($saved); | |
unlink($dest_file_name); | |
} | |
return null; | |
} | |
// Add the resized dimensions and alignment to original image metadata, so the images can be deleted when the original image is delete from the Media Library | |
if ($get_attachment) { | |
$metadata = wp_get_attachment_metadata($get_attachment[0]->ID); | |
if (isset($metadata['image_meta'])) { | |
$md = $saved['width'] . 'x' . $saved['height']; | |
if ($crop) $md .= ($align) ? "_${align}" : "_c"; | |
$metadata['image_meta']['resized_images'][] = $md; | |
wp_update_attachment_metadata($get_attachment[0]->ID, $metadata); | |
} | |
} | |
$resized_url = str_replace(basename($url), basename($saved['path']), $url); | |
} else { | |
$resized_url = str_replace(basename($url), basename($dest_file_name), $url); | |
} | |
return $resized_url; | |
} | |
// Returns common information shared by processing functions | |
function cerchez_common_info($args) { | |
list($url, $width, $height, $crop, $align, $retina) = $args; | |
if (empty($url)) { | |
return is_user_logged_in() ? "image_not_specified" : null; | |
} | |
// Return if nocrop is set on query string | |
if (preg_match('/(\?|&)nocrop/', $url)) { | |
return $url; | |
} | |
// Get the image file path | |
$urlinfo = parse_url($url); | |
$wp_upload_dir = wp_upload_dir(); | |
if (preg_match('/\/[0-9]{4}\/[0-9]{2}\/.+$/', $urlinfo['path'], $matches)) { | |
$file_path = $wp_upload_dir['basedir'] . $matches[0]; | |
} else { | |
$pathinfo = parse_url( $url ); | |
$uploads_dir = is_multisite() ? '/files/' : '/wp-content/'; | |
$file_path = ABSPATH . str_replace(dirname($_SERVER['SCRIPT_NAME']) . '/', '', strstr($pathinfo['path'], $uploads_dir)); | |
$file_path = preg_replace('/(\/\/)/', '/', $file_path); | |
} | |
if (!file_exists($file_path)) { | |
return null; | |
} | |
$size = is_user_logged_in() ? getimagesize($file_path) : @getimagesize($file_path); | |
if (!$size) { | |
return is_user_logged_in() ? "getimagesize_error_common" : null; | |
} | |
list($orig_width, $orig_height, $orig_type) = $size; | |
if ($width && !$height) { | |
$height = floor ($orig_height * ($width / $orig_width)); | |
} else if ($height && !$width) { | |
$width = floor ($orig_width * ($height / $orig_height)); | |
} else if (!$width && !$height) { | |
return $url; | |
} | |
$retina = $retina ? ($retina === true ? 2 : $retina) : 1; | |
$dest_width = $width * $retina; | |
$dest_height = $height * $retina; | |
$info = pathinfo($file_path); | |
$dir = $info['dirname']; | |
$ext = $info['extension']; | |
$name = wp_basename($file_path, ".$ext"); | |
$suffix = "${dest_width}x${dest_height}"; | |
if ($crop) { | |
$suffix .= ($align) ? "_${align}" : "_c"; | |
} | |
$dest_file_name = "${dir}/${name}-${suffix}.${ext}"; | |
return array( | |
'dir' => $dir, | |
'name' => $name, | |
'ext' => $ext, | |
'suffix' => $suffix, | |
'orig_width' => $orig_width, | |
'orig_height' => $orig_height, | |
'orig_type' => $orig_type, | |
'dest_width' => $dest_width, | |
'dest_height' => $dest_height, | |
'file_path' => $file_path, | |
'dest_file_name' => $dest_file_name, | |
); | |
} | |
// Deletes the resized images when the original image is deleted from the WordPress Media Library | |
function cerchez_delete_resized_images($post_id) { | |
$metadata = wp_get_attachment_metadata($post_id); | |
if (!$metadata) return; | |
if (!isset($metadata['file']) || !isset($metadata['image_meta']['resized_images'])) return; | |
$wp_upload_dir = wp_upload_dir(); | |
$pathinfo = pathinfo($metadata['file']); | |
$resized_images = $metadata['image_meta']['resized_images']; | |
foreach ($resized_images as $dims) { | |
$file = $wp_upload_dir['basedir'] . '/' . $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '-' . $dims . '.' . $pathinfo['extension']; | |
is_user_logged_in() ? unlink($file) : @unlink($file); | |
} | |
} | |
function ricca_get_image_id( $local_url ) { | |
global $wpdb; | |
$attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid=%s;", $local_url ) ); | |
if ( count( $attachment ) > 0 ) { | |
return $attachment[0]; | |
} else { | |
return false; | |
} | |
} | |
function ricca_resize_image( $url, $width = 810, $height = 456 ) { | |
// Validate inputs. | |
if ( ! $url || ( ! $width && ! $height ) ) { | |
return false; | |
} | |
$crop = true; | |
add_filter( 'image_resize_dimensions', 'ricca_temporary_upscale', 10, 6 ); //100% safe - ignore theme check nag | |
// Define upload path & dir. | |
$upload_info = wp_upload_dir(); | |
$upload_dir = $upload_info['basedir']; | |
$upload_url = $upload_info['baseurl']; | |
if ( is_ssl() && 'http:' == substr( $upload_url, 0, 5 ) ) { | |
$upload_url = 'https:' . substr( $upload_url, 5 ); | |
} | |
if ( is_ssl() && 'http:' == substr( $url, 0, 5 ) ) { | |
$url = 'https:' . substr( $url, 5 ); | |
} | |
// Check if $img_url is remote. | |
if ( false === strpos( $url, $upload_url ) ) { | |
$file_array = array(); | |
$extension_available = false; | |
preg_match( '/[^\?]+\.(jpg|jpe|jpeg|gif|png)/i', $url, $matches ); | |
if ( 0 == count( $matches ) ) { | |
$matches[0] = $url; | |
$matches[1] = md5( $url ); | |
} else { | |
$extension_available = true; | |
} | |
$file_array['name'] = basename( $matches[0] ); | |
// check if attachment already exists. | |
$attachment_args = array( | |
'posts_per_page' => 1, | |
'post_type' => 'attachment', | |
'post_mime_type' => 'image', | |
'name' => basename( $matches[0], '.' . $matches[1] ), | |
); | |
$attachment_check = new Wp_Query( $attachment_args ); | |
if ( $attachment_check->have_posts() ) { | |
$url = wp_get_attachment_url( $attachment_check->post->ID ); | |
} else { | |
// download remote image via WordPress functions. | |
if ( ! function_exists( 'media_handle_sideload' ) ) { | |
require_once( ABSPATH . 'wp-admin/includes/image.php' ); | |
require_once( ABSPATH . 'wp-admin/includes/file.php' ); | |
require_once( ABSPATH . 'wp-admin/includes/media.php' ); | |
} | |
$tmp = download_url( $url ); | |
if ( is_wp_error( $tmp ) ) { | |
return false; | |
} else { | |
if ( ! $extension_available ) { | |
// get extension for an unknown remote image file | |
$tmp_image_data = getimagesize( $tmp ); | |
if ( $tmp_image_data && isset( $tmp_image_data[2] ) ) { | |
$extension = image_type_to_extension( $tmp_image_data[2] ); | |
$new_tmp_file = str_replace( '.tmp', '', $tmp ); | |
if ( rename( $tmp, $new_tmp_file . $extension ) ) { | |
$tmp = $new_tmp_file . $extension; | |
} | |
$file_array['type'] = image_type_to_mime_type( $tmp_image_data[2] ); | |
$file_array['error'] = 0; | |
$file_array['size'] = filesize( $tmp ); | |
} | |
} | |
$file_array['tmp_name'] = $tmp; | |
$attachment_id = media_handle_sideload( $file_array, 0, basename( $matches[0], '.' . $matches[1] ) ); | |
if ( is_wp_error( $attachment_id ) ) { | |
return false; | |
} else { | |
$url = wp_get_attachment_url( $attachment_id ); | |
} | |
} | |
} | |
} | |
// Define path of image. | |
$rel_path = str_replace( $upload_url, '', $url ); | |
$img_path = $upload_dir . $rel_path; | |
//check if img path exists, and is an image indeed | |
if ( ! file_exists( $img_path ) || ! getimagesize( $img_path ) ) { | |
return false; | |
} | |
// Get image info. | |
$info = pathinfo( $img_path ); | |
$ext = $info['extension']; | |
list( $orig_w, $orig_h ) = getimagesize( $img_path ); | |
// Get image size after cropping. | |
$dims = image_resize_dimensions( $orig_w, $orig_h, $width, $height, $crop ); //100% safe - ignore theme check nag | |
$dst_w = $dims[4]; | |
$dst_h = $dims[5]; | |
// Return the original image only if it exactly fits the needed measures. | |
if ( ! $dims && ( ( ( null === $height && $orig_w == $width ) xor ( null === $width && $orig_h == $height ) ) xor ( $height == $orig_h && $width == $orig_w ) ) ) { | |
$img_url = $url; | |
$dst_w = $orig_w; | |
$dst_h = $orig_h; | |
} else { | |
// Use this to check if cropped image already exists, so we can return that instead. | |
$suffix = "{$dst_w}x{$dst_h}"; | |
$dst_rel_path = str_replace( '.' . $ext, '', $rel_path ); | |
$destfilename = "{$upload_dir}{$dst_rel_path}-{$suffix}.{$ext}"; | |
if ( ! $dims || ( $crop && ( $dst_w < $width || $dst_h < $height ) ) ) { | |
// Can't resize, so return false saying that the action to do could not be processed as planned. | |
return false; | |
} elseif ( file_exists( $destfilename ) && getimagesize( $destfilename ) ) { // check if cache exists. | |
$img_url = "{$upload_url}{$dst_rel_path}-{$suffix}.{$ext}"; | |
} else { | |
if ( function_exists( 'wp_get_image_editor' ) ) { // we resize the image and return the new resized image url. | |
$editor = wp_get_image_editor( $img_path ); | |
if ( is_wp_error( $editor ) || is_wp_error( $editor->resize( $width, $height, $crop ) ) ) { | |
return false; | |
} | |
$editor->set_quality( 90 ); | |
$resized_file = $editor->save(); | |
if ( ! is_wp_error( $resized_file ) ) { | |
$resized_rel_path = str_replace( $upload_dir, '', $resized_file['path'] ); | |
$img_url = $upload_url . $resized_rel_path; | |
// Add the resized dimensions to original image metadata (so we can delete our resized images when the original image is deleted from the Media Library). | |
global $wpdb; | |
$get_attachment = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE guid=%s", $url ) ); | |
if ( ! $get_attachment ) { | |
return $url; | |
} | |
$metadata = wp_get_attachment_metadata( $get_attachment[0]->ID ); | |
if ( isset( $metadata['sizes'] ) ) { | |
$metadata['sizes'][ 'crop_' . $dst_w . '_' . $dst_h ] = array( | |
'file' => $resized_file['file'], | |
'width' => $resized_file['width'], | |
'height' => $resized_file['height'], | |
'mime-type' => $resized_file['mime-type'], | |
); | |
wp_update_attachment_metadata( $get_attachment[0]->ID, $metadata ); | |
} | |
} else { | |
return false; | |
} | |
} else { | |
return false; | |
} | |
} | |
} | |
// Return the output. | |
$image = $img_url; | |
// RETINA Support. | |
$retina_w = $dst_w * 2; | |
$retina_h = $dst_h * 2; | |
//get image size after cropping | |
$dims_x2 = image_resize_dimensions( $orig_w, $orig_h, $retina_w, $retina_h, $crop ); //100% safe - ignore theme check nag | |
$dst_x2_w = $dims_x2[4]; | |
$dst_x2_h = $dims_x2[5]; | |
// If possible lets make the @2x image. | |
if ( $dst_x2_h ) { | |
// @2x image url. | |
$destfilename = "{$upload_dir}{$dst_rel_path}-{$suffix}@2x.{$ext}"; | |
// check if retina image exists. | |
if ( file_exists( $destfilename ) && getimagesize( $destfilename ) ) { | |
// already exists, do nothing. | |
} else { | |
// doesnt exist, lets create it. | |
$editor = wp_get_image_editor( $img_path ); | |
if ( ! is_wp_error( $editor ) ) { | |
$editor->resize( $retina_w, $retina_h, $crop ); | |
$editor->set_quality( 80 ); | |
$filename = $editor->generate_filename( $dst_w . 'x' . $dst_h . '@2x' ); | |
$resized_file = $editor->save( $filename ); | |
// Add the resized dimensions to original image metadata (so we can delete our resized retina images when the original image is delete from the Media Library) | |
global $wpdb; | |
$get_attachment = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE guid=%s", $url ) ); | |
if ( ! $get_attachment ) { | |
return $url; | |
} | |
$metadata = wp_get_attachment_metadata( $get_attachment[0]->ID ); | |
if ( isset( $metadata['sizes'] ) ) { | |
$metadata['sizes'][ 'crop_' . $dst_w . '_' . $dst_h . '_@2x' ] = array( | |
'file' => $resized_file['file'], | |
'width' => $resized_file['width'], | |
'height' => $resized_file['height'], | |
'mime-type' => $resized_file['mime-type'], | |
); | |
wp_update_attachment_metadata( $get_attachment[0]->ID, $metadata ); | |
} | |
} | |
} | |
} | |
remove_filter( 'image_resize_dimensions', 'ricca_temporary_upscale' ); //100% safe - ignore theme check nag | |
return $image; | |
} | |
/** | |
* Callback to overwrite WP computing of thumbnail measures temporary for private function. | |
*/ | |
function ricca_temporary_upscale( $default, $orig_w, $orig_h, $dest_w, $dest_h, $crop ) { | |
if ( ! $crop ) { | |
return null; // Let the WordPress default function handle this. | |
} | |
// Here is the point we allow to use larger image size than the original one. | |
$aspect_ratio = $orig_w / $orig_h; | |
$new_w = $dest_w; | |
$new_h = $dest_h; | |
if ( ! $new_w ) { | |
$new_w = intval( $new_h * $aspect_ratio ); | |
} | |
if ( ! $new_h ) { | |
$new_h = intval( $new_w / $aspect_ratio ); | |
} | |
$size_ratio = max( $new_w / $orig_w, $new_h / $orig_h ); | |
$crop_w = round( $new_w / $size_ratio ); | |
$crop_h = round( $new_h / $size_ratio ); | |
$s_x = floor( ( $orig_w - $crop_w ) / 2 ); | |
$s_y = floor( ( $orig_h - $crop_h ) / 2 ); | |
return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment