Skip to content

Instantly share code, notes, and snippets.

@liviucerchez
Created February 19, 2018 10:18
Show Gist options
  • Save liviucerchez/136b3bd59819527ebfda306d44c4626a to your computer and use it in GitHub Desktop.
Save liviucerchez/136b3bd59819527ebfda306d44c4626a to your computer and use it in GitHub Desktop.
custom image resize
<?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