¿Cómo puedo hacer que add_image_size() recorte desde la parte superior?
Tengo una serie de publicaciones, todas con imágenes destacadas, pero necesito poder personalizar el recorte en la esquina superior derecha. En este caso, necesito que se recorten desde la parte superior derecha, pero también sería útil saber cómo posicionar ese punto yo mismo.
Actualmente, la función add_image_size() está tomando su recorte desde el centro de la imagen. ¡No siempre queda bien!

El Codex de WordPress tiene la respuesta, está a continuación.
Establece el tamaño de la imagen recortándola y definiendo una posición de recorte:
add_image_size( 'custom-size', 220, 220, array( 'left', 'top' ) ); // Recorte duro arriba a la izquierda
Al establecer una posición de recorte, el primer valor en el array es la posición de recorte en el eje x, el segundo es la posición de recorte en el eje y.
x_crop_position acepta 'left', 'center' o 'right'. y_crop_position acepta 'top', 'center' o 'bottom'. Por defecto, estos valores se establecen en 'center' cuando se usa el modo de recorte duro.
Y también el Codex hace referencia a una página que muestra cómo actúan las posiciones de recorte.
http://havecamerawilltravel.com/photographer/wordpress-thumbnail-crop

La generación de imágenes intermedias es extremadamente rígida. La función image_resize()
mantiene el proceso muy cercano al código y carece completamente de hooks.
Básicamente, la única opción para esto es engancharse a wp_generate_attachment_metadata
y sobrescribir la imagen generada por WP con la propia (lo que requerirá hacer un fork de image_resize()
).
Necesito esto para el trabajo, así que quizás pueda compartir algo de código más adelante.
Bien, aquí hay un ejemplo aproximado pero funcional. Ten en cuenta que configurar el recorte de esta manera requiere entender imagecopyresampled()
.
add_filter('wp_generate_attachment_metadata', 'custom_crop');
function custom_crop($metadata) {
$uploads = wp_upload_dir();
$file = path_join( $uploads['basedir'], $metadata['file'] ); // archivo de imagen original
list( $year, $month ) = explode( '/', $metadata['file'] );
$target = path_join( $uploads['basedir'], "{$year}/{$month}/".$metadata['sizes']['medium']['file'] ); // archivo de tamaño intermedio
$image = imagecreatefromjpeg($file); // recurso de imagen original
$image_target = wp_imagecreatetruecolor( 44, 44 ); // imagen en blanco para rellenar
imagecopyresampled($image_target, $image, 0, 0, 25, 15, 44, 44, 170, 170); // recortar original
imagejpeg($image_target, $target, apply_filters( 'jpeg_quality', 90, 'image_resize' )); // escribir recorte en archivo
return $metadata;
}

No, meterse con el núcleo sería cambiar la función image_resize
. Rarst estaba señalando que tendrías que engancharte al proceso de redimensionamiento, pero crear los tamaños de imagen manualmente por tu cuenta.

¿Puedo preguntar si esto todavía funciona? Acabo de implementar el hook en mi archivo functions.php y tengo funciones add_image_size() configuradas, pero las imágenes recortadas todavía se recortan desde el centro hacia afuera.

@cr0z3r No conozco ninguna razón por la que no funcione. Pero ten en cuenta que esto es solo un ejemplo aproximado de prueba de concepto, en lugar de un código significativo y confiable.

He desarrollado una solución a este problema que no requiere modificar el núcleo: http://bradt.ca/archives/image-crop-position-in-wordpress/
También he enviado un parche al núcleo: http://core.trac.wordpress.org/ticket/19393
Agrégate como Cc en el ticket para mostrar tu apoyo a que se incluya en el núcleo.

Puedes usar el plugin Thumbnail Crop Position para seleccionar la posición de recorte de tus miniaturas.

Solución alternativa aquí: http://pixert.com/blog/cropping-post-featured-thumbnails-from-top-instead-of-center-in-wordpress-with-native-cropping-tool/
Simplemente añade este código al archivo functions.php, luego usa el plugin "Regenerate Thumbnails" (https://wordpress.org/plugins/regenerate-thumbnails/):
function px_image_resize_dimensions( $payload, $orig_w, $orig_h, $dest_w, $dest_h, $crop ){
// Cambia esto por una condición que decida si deseas anular los valores predeterminados para esta imagen o no.
if( false )
return $payload;
if ( $crop ) {
// Recorta la porción más grande posible de la imagen original que podamos redimensionar a $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; // [[ anteriormente ]] ==> floor( ($orig_w - $crop_w) / 2 );
$s_y = 0; // [[ anteriormente ]] ==> floor( ($orig_h - $crop_h) / 2 );
} else {
// no recortar, solo redimensionar usando $dest_w x $dest_h como cuadro delimitador máximo
$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 );
}
// si la imagen resultante tendría el mismo tamaño o más grande, no queremos redimensionarla
if ( $new_w >= $orig_w && $new_h >= $orig_h )
return false;
// el array de retorno coincide con los parámetros de 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 );

Hola Niente0, bienvenido a WPSE y gracias por tu respuesta. ¿Te importaría editar tu publicación para explicar qué hace tu código? Las publicaciones en los sitios de StackExchange deben explicar sus soluciones, e incluir enlaces externos solo como referencias, no como soluciones completas. ¡Gracias de nuevo!
