image_resize_dimensions()WP 2.5.0

Получает размеры и координаты для изменения размера изображения так, чтобы оно поместилось в заданную ширину и высоту.

Используется при создании уменьшенных копий изображений. Функция рассчитывает, какую часть исходного изображения нужно взять и до какого размера её уменьшить или обрезать.

Если обрезка отключена, изображение масштабируется с сохранением пропорций. Если обрезка включена, изображение подгоняется под заданный размер и лишняя часть отсекается.

Функция не изменяет файл изображения сама по себе. Она только рассчитывает координаты и размеры, которые потом могут использоваться при ресайзе изображения.

Если новый размер больше исходного изображения, функция обычно вернёт false, чтобы не создавать увеличенную копию.

Работает на основе: wp_constrain_dimensions(), wp_fuzzy_number_match()

Возвращает

Массив|false.

  • array — массив с размерами и координатами в формате, подходящем для imagecopyresampled(): [dst_x, dst_y, src_x, src_y, dst_w, dst_h, src_w, src_h].
  • false — если исходные размеры некорректны, не указан новый размер, новый размер больше исходного или новый размер практически совпадает с исходным.

Использование

image_resize_dimensions( $orig_w, $orig_h, $dest_w, $dest_h, $crop );
$orig_w(int) (обязательный)
Ширина исходного изображения в пикселях.
$orig_h(int) (обязательный)
Высота исходного изображения в пикселях.
$dest_w(int) (обязательный)
Новая ширина изображения в пикселях. Можно передать 0, если размер нужно рассчитать по высоте.
$dest_h(int) (обязательный)
Новая высота изображения в пикселях. Можно передать 0, если размер нужно рассчитать по ширине.
$crop(bool|array)

Определяет, нужно ли обрезать изображение.

Если false, изображение масштабируется с сохранением пропорций.

Если true, изображение обрезается по центру.

Если передать массив, можно указать позицию обрезки:
первое значение для оси X (left, center, right),
второе — для оси Y (top, center, bottom).

По умолчанию: false

Примеры

0

#1 Получение размеров для обычного масштабирования

Изображение будет уменьшено так, чтобы поместиться в область 300x300 без обрезки.

$dimensions = image_resize_dimensions( 1200, 800, 300, 300 );

if ( false !== $dimensions ) {
	list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dimensions;

	echo 'Новый размер: ' . $dst_w . 'x' . $dst_h;
}
0

#2 Получение размеров для обрезки по центру

Изображение будет обрезано и подогнано под размер 300x300.

$dimensions = image_resize_dimensions( 1200, 800, 300, 300, true );

if ( false !== $dimensions ) {
	list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dimensions;

	echo 'Обрезка начинается с точки: ' . $src_x . 'x' . $src_y;
}
0

#3 Обрезка изображения от верхнего левого угла

Можно указать, откуда брать область изображения для обрезки.

$dimensions = image_resize_dimensions( 1200, 800, 300, 300, [ 'left', 'top' ] );

if ( false !== $dimensions ) {
	list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dimensions;

	echo 'Источник: ' . $src_x . 'x' . $src_y;
}
0

#4 Изменение результата через фильтр

Фильтр image_resize_dimensions позволяет полностью заменить стандартный расчёт размеров.

add_filter( 'image_resize_dimensions', 'my_image_resize_dimensions', 10, 6 );

function my_image_resize_dimensions( $output, $orig_w, $orig_h, $dest_w, $dest_h, $crop ) {
	if ( 300 === $dest_w && 300 === $dest_h ) {
		return [ 0, 0, 0, 0, 300, 300, min( 300, $orig_w ), min( 300, $orig_h ) ];
	}

	return $output;
}

Список изменений

С версии 2.5.0 Введена.

Код image_resize_dimensions() WP 7.0

function image_resize_dimensions( $orig_w, $orig_h, $dest_w, $dest_h, $crop = false ) {

	if ( $orig_w <= 0 || $orig_h <= 0 ) {
		return false;
	}
	// At least one of $dest_w or $dest_h must be specific.
	if ( $dest_w <= 0 && $dest_h <= 0 ) {
		return false;
	}

	/**
	 * Filters whether to preempt calculating the image resize dimensions.
	 *
	 * Returning a non-null value from the filter will effectively short-circuit
	 * image_resize_dimensions(), returning that value instead.
	 *
	 * @since 3.4.0
	 *
	 * @param null|mixed $null   Whether to preempt output of the resize dimensions.
	 * @param int        $orig_w Original width in pixels.
	 * @param int        $orig_h Original height in pixels.
	 * @param int        $dest_w New width in pixels.
	 * @param int        $dest_h New height in pixels.
	 * @param bool|array $crop   Whether to crop image to specified width and height or resize.
	 *                           An array can specify positioning of the crop area. Default false.
	 */
	$output = apply_filters( 'image_resize_dimensions', null, $orig_w, $orig_h, $dest_w, $dest_h, $crop );

	if ( null !== $output ) {
		return $output;
	}

	// Stop if the destination size is larger than the original image dimensions.
	if ( empty( $dest_h ) ) {
		if ( $orig_w < $dest_w ) {
			return false;
		}
	} elseif ( empty( $dest_w ) ) {
		if ( $orig_h < $dest_h ) {
			return false;
		}
	} else {
		if ( $orig_w < $dest_w && $orig_h < $dest_h ) {
			return false;
		}
	}

	if ( $crop ) {
		/*
		 * Crop the largest possible portion of the original image that we can size to $dest_w x $dest_h.
		 * Note that the requested crop dimensions are used as a maximum bounding box for the original image.
		 * If the original image's width or height is less than the requested width or height
		 * only the greater one will be cropped.
		 * For example when the original image is 600x300, and the requested crop dimensions are 400x400,
		 * the resulting image will be 400x300.
		 */
		$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 = (int) round( $new_h * $aspect_ratio );
		}

		if ( ! $new_h ) {
			$new_h = (int) round( $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 );

		if ( ! is_array( $crop ) || count( $crop ) !== 2 ) {
			$crop = array( 'center', 'center' );
		}

		list( $x, $y ) = $crop;

		if ( 'left' === $x ) {
			$s_x = 0;
		} elseif ( 'right' === $x ) {
			$s_x = $orig_w - $crop_w;
		} else {
			$s_x = floor( ( $orig_w - $crop_w ) / 2 );
		}

		if ( 'top' === $y ) {
			$s_y = 0;
		} elseif ( 'bottom' === $y ) {
			$s_y = $orig_h - $crop_h;
		} else {
			$s_y = floor( ( $orig_h - $crop_h ) / 2 );
		}
	} else {
		// 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 ( wp_fuzzy_number_match( $new_w, $orig_w ) && wp_fuzzy_number_match( $new_h, $orig_h ) ) {
		// The new size has virtually the same dimensions as the original image.

		/**
		 * Filters whether to proceed with making an image sub-size with identical dimensions
		 * with the original/source image. Differences of 1px may be due to rounding and are ignored.
		 *
		 * @since 5.3.0
		 *
		 * @param bool $proceed The filtered value.
		 * @param int  $orig_w  Original image width.
		 * @param int  $orig_h  Original image height.
		 */
		$proceed = (bool) apply_filters( 'wp_image_resize_identical_dimensions', false, $orig_w, $orig_h );

		if ( ! $proceed ) {
			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 );
}