How can I make add_image_size() crop from the top?

I have a series of posts, all with featured images, but I need to be able to customise the crop top right corner. In this instance, I need them to be cropped from top right, but it would be useful to also know how to position that point myself.

At present, the add_image_size() function is taking its crop from the centre of the image. Not always pretty!!

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Intermediate image generation is extremely rigid. image_resize() keeps it close to code and completely lacks hooks.

Pretty much only option for this is to hook into wp_generate_attachment_metadata and overwrite WP-generated image with your own (which will need bit of a image_resize() fork).

I need this for work so I might be able to share some code later.

Ok, here is rough, but working example. Note that setting up crop in this way requires understanding of imagecopyresampled().

add_filter('wp_generate_attachment_metadata', 'custom_crop');

function custom_crop($metadata) {

    $uploads = wp_upload_dir();
    $file = path_join( $uploads['basedir'], $metadata['file'] ); // original image file
    list( $year, $month ) = explode( '/', $metadata['file'] );
    $target = path_join( $uploads['basedir'], "{$year}/{$month}/".$metadata['sizes']['medium']['file'] ); // intermediate size file
    $image = imagecreatefromjpeg($file); // original image resource
    $image_target = wp_imagecreatetruecolor( 44, 44 ); // blank image to fill
    imagecopyresampled($image_target, $image, 0, 0, 25, 15, 44, 44, 170, 170); // crop original
    imagejpeg($image_target, $target, apply_filters( 'jpeg_quality', 90, 'image_resize' )); // write cropped to file

    return $metadata;
}

Method 2

WordPress codex has the answer, its below.

Set the image size by cropping the image and defining a crop position:

add_image_size( 'custom-size', 220, 220, array( 'left', 'top' ) ); // Hard crop left top

When setting a crop position, the first value in the array is the x
axis crop position, the second is the y axis crop position.

x_crop_position accepts ‘left’ ‘center’, or ‘right’. y_crop_position
accepts ‘top’, ‘center’, or ‘bottom’. By default, these values default
to ‘center’ when using hard crop mode.

And also codex references a page which shows how crop positions acts.

http://havecamerawilltravel.com/photographer/wordpress-thumbnail-crop

Method 3

I have developed a solution to this problem that does not require hacking the core: http://bradt.ca/archives/image-crop-position-in-wordpress/

I have also submitted a patch to core:
http://core.trac.wordpress.org/ticket/19393

Add yourself as a Cc on the ticket to show your support for it to be added to core.

Method 4

You can use the plugin Thumbnail Crop Position to select the crop position of your thumbnails.

Method 5

Alternative solution here: http://pixert.com/blog/cropping-post-featured-thumbnails-from-top-instead-of-center-in-wordpress-with-native-cropping-tool/

Just add this code to functions.php, then use “Regenerate Thumbnails” plugin (https://wordpress.org/plugins/regenerate-thumbnails/):

function px_image_resize_dimensions( $payload, $orig_w, $orig_h, $dest_w, $dest_h, $crop ){

// Change this to a conditional that decides whether you want to override the defaults for this image or not.
if( false )
return $payload;

if ( $crop ) {
// crop the largest possible portion of the original image that we can size to $dest_w x $dest_h
$aspect_ratio = $orig_w / $orig_h;
$new_w = min($dest_w, $orig_w);
$new_h = min($dest_h, $orig_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 = 0; // [[ formerly ]] ==> floor( ($orig_w - $crop_w) / 2 );
$s_y = 0; // [[ formerly ]] ==> floor( ($orig_h - $crop_h) / 2 );
} else {
// don't crop, just resize using $dest_w x $dest_h as a maximum bounding box
$crop_w = $orig_w;
$crop_h = $orig_h;

$s_x = 0;
$s_y = 0;

list( $new_w, $new_h ) = wp_constrain_dimensions( $orig_w, $orig_h, $dest_w, $dest_h );
}

// if the resulting image would be the same size or larger we don't want to resize it
if ( $new_w >= $orig_w && $new_h >= $orig_h )
return false;

// the return array matches the parameters to imagecopyresampled()
// int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h
return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h );

}
add_filter( 'image_resize_dimensions', 'px_image_resize_dimensions', 10, 6 );


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x