深入理解 `add_image_size()` 函数的源码,它是如何注册新的图片尺寸的?

大家好,欢迎来到今天的“WordPress图像魔法:add_image_size() 源码解剖”讲座。我是你们今天的导游,皮卡丘(虽然我不能放图片,请自行脑补)。今天咱们不聊花里胡哨的,直接撸起袖子,扒一扒 WordPress 里 add_image_size() 这个看似简单的函数,看看它到底是怎么把新的图片尺寸塞进 WordPress 的“小脑瓜”里的。

准备好了吗? Let’s dive in!

一、add_image_size() 的基本用法:先打个照面

在深入源码之前,咱们先复习一下 add_image_size() 的基本用法。这就像给你的武功秘籍先翻到第一页,看看总纲是什么。

add_image_size( string $name, int $width, int $height, bool|array $crop = false );
  • $name: 这是你给这个新尺寸起的名字,以后要用这个名字来调用它。比如,'my-custom-thumbnail'
  • $width: 图片的宽度,单位是像素。
  • $height: 图片的高度,单位是像素。
  • $crop: 一个布尔值或数组,决定是否裁剪图片。
    • true: 强制裁剪图片到指定的宽高。
    • false: 保持原始比例,可能会导致图片小于指定的宽高。
    • array( 'x_position', 'y_position' ): 指定裁剪的起始位置。例如,array( 'left', 'top' ) 从左上角开始裁剪。

举个栗子:

add_image_size( 'my-custom-thumbnail', 200, 200, true ); // 创建一个 200x200 的正方形缩略图,强制裁剪。

So easy! 但是,问题来了:WordPress 内部是怎么处理这个函数的呢? 它把这些信息存在哪里了? 别急,咱们这就进入源码的世界。

二、深入源码:探秘 WordPress 的“小脑瓜”

add_image_size() 函数的定义位于 wp-includes/media.php 文件中。 咱们一点一点地解剖它。

function add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
    global $_wp_additional_image_sizes;

    $name = strtolower( trim( $name ) );

    if ( ! isset( $_wp_additional_image_sizes[ $name ] ) ) {
        $_wp_additional_image_sizes[ $name ] = array(
            'width'  => absint( $width ),
            'height' => absint( $height ),
            'crop'   => $crop,
        );
    }
}

看起来是不是很简单? 咱们来逐行分析:

  1. global $_wp_additional_image_sizes;: 这行代码声明了一个全局变量 $_wp_additional_image_sizes。 重点来了! 这个变量就是 WordPress 用来存储所有自定义图片尺寸的地方。 它是一个数组,以图片尺寸的名字作为键,以包含宽度、高度和裁剪信息的数组作为值。 就像一个“尺寸信息登记表”。

  2. $name = strtolower( trim( $name ) );: 这行代码对图片尺寸的名字进行了一些处理:

    • trim(): 去除名字首尾的空格。
    • strtolower(): 将名字转换为小写。
      这保证了名字的规范性,避免因为大小写或者空格导致的问题。
  3. if ( ! isset( $_wp_additional_image_sizes[ $name ] ) ) { ... }: 这行代码检查是否已经存在同名的图片尺寸。 如果不存在,才会添加新的尺寸。 这避免了重复注册同一个尺寸。

  4. $_wp_additional_image_sizes[ $name ] = array( ... );: 这行代码才是真正的“注册”操作。 它将新的图片尺寸信息添加到 $_wp_additional_image_sizes 数组中。

    • 'width' => absint( $width ),: 将宽度转换为绝对整数。
    • 'height' => absint( $height ),: 将高度转换为绝对整数。
    • 'crop' => $crop,: 保留裁剪信息。

总结一下:

add_image_size() 函数实际上就是往全局变量 $_wp_additional_image_sizes 数组里添加一条记录,记录了图片尺寸的名字、宽度、高度和裁剪信息。 这个数组就是 WordPress 的“自定义图片尺寸数据库”。

三、$_wp_additional_image_sizes:自定义尺寸的大本营

现在,咱们来仔细看看 $_wp_additional_image_sizes 这个全局变量。 它是一个关联数组,结构如下:

$_wp_additional_image_sizes = array(
    'size-name' => array(
        'width'  => int,
        'height' => int,
        'crop'   => bool|array,
    ),
    'another-size' => array(
        'width'  => int,
        'height' => int,
        'crop'   => bool|array,
    ),
    // ... 更多自定义尺寸
);
  • 键 (Key): 图片尺寸的名字(例如:'my-custom-thumbnail')。
  • 值 (Value): 一个包含宽度、高度和裁剪信息的数组。

示例:

假设你添加了两个自定义尺寸:

add_image_size( 'my-custom-thumbnail', 200, 200, true );
add_image_size( 'my-large-image', 800, 600, false );

那么,$_wp_additional_image_sizes 数组的内容可能如下所示:

Array
(
    [my-custom-thumbnail] => Array
        (
            [width] => 200
            [height] => 200
            [crop] => 1
        )

    [my-large-image] => Array
        (
            [width] => 800
            [height] => 600
            [crop] =>
        )

)

四、get_intermediate_image_sizes():获取所有图片尺寸

WordPress 提供了 get_intermediate_image_sizes() 函数来获取所有可用的图片尺寸,包括 WordPress 默认的尺寸和通过 add_image_size() 添加的自定义尺寸。

$sizes = get_intermediate_image_sizes();
print_r( $sizes );

输出结果可能如下:

Array
(
    [0] => thumbnail
    [1] => medium
    [2] => medium_large
    [3] => large
    [4] => 1536x1536
    [5] => 2048x2048
    [6] => my-custom-thumbnail
    [7] => my-large-image
)

可以看到,get_intermediate_image_sizes() 函数返回一个包含所有图片尺寸名字的数组。 这让你可以在代码中动态地获取所有可用的图片尺寸。

五、wp_get_attachment_image_src():获取指定尺寸的图片 URL

有了图片尺寸的名字,咱们就可以使用 wp_get_attachment_image_src() 函数来获取指定尺寸的图片 URL。

$attachment_id = 123; // 假设附件 ID 是 123
$size = 'my-custom-thumbnail'; // 使用我们自定义的尺寸名字

$image_data = wp_get_attachment_image_src( $attachment_id, $size );

if ( $image_data ) {
    $image_url = $image_data[0]; // 图片 URL
    $image_width = $image_data[1]; // 图片宽度
    $image_height = $image_data[2]; // 图片高度
    $is_intermediate = $image_data[3]; // 是否是中间尺寸
    echo '<img src="' . esc_url( $image_url ) . '" width="' . esc_attr( $image_width ) . '" height="' . esc_attr( $image_height ) . '" alt="My Custom Thumbnail">';
} else {
    echo 'No image found for this size.';
}

wp_get_attachment_image_src() 函数返回一个数组,包含了图片 URL、宽度、高度和是否是中间尺寸的信息。 你可以使用这些信息来显示图片。

六、幕后英雄:_wp_image_editor_choose()wp_generate_attachment_metadata()

add_image_size() 只是告诉 WordPress 你想要哪些尺寸的图片。 真正生成这些图片的是 _wp_image_editor_choose()wp_generate_attachment_metadata() 这两个函数。

  • _wp_image_editor_choose(): 这个函数负责选择合适的图像编辑器(通常是 GD 或 Imagick)来处理图片。 WordPress 会根据你的服务器环境和配置选择最佳的图像编辑器。

  • wp_generate_attachment_metadata(): 这个函数在上传图片时被调用,它会生成图片的元数据,包括各种尺寸的图片。 它会遍历 $_wp_additional_image_sizes 数组,并使用选定的图像编辑器生成每个尺寸的图片。

七、自定义裁剪:$crop 参数的进阶用法

咱们再来深入一下 $crop 参数。 除了 truefalse 之外,它还可以是一个数组,用于指定裁剪的起始位置。

add_image_size( 'my-custom-thumbnail', 200, 200, array( 'left', 'top' ) ); // 从左上角开始裁剪
add_image_size( 'my-custom-thumbnail', 200, 200, array( 'center', 'center' ) ); // 从中心开始裁剪
add_image_size( 'my-custom-thumbnail', 200, 200, array( 'right', 'bottom' ) ); // 从右下角开始裁剪

$crop 数组的第一个元素指定水平方向的裁剪位置,第二个元素指定垂直方向的裁剪位置。 可选的值包括:'left', 'center', 'right', 'top', 'bottom'

八、实战演练:创建一个响应式图片尺寸

现在,咱们来做一个更有趣的例子:创建一个响应式图片尺寸。 这意味着我们要根据屏幕宽度选择合适的图片尺寸。

function my_responsive_image_sizes( $sizes ) {
    $custom_sizes = array(
        'my-small-thumbnail'  => __( 'My Small Thumbnail (320px)', 'my-theme' ),
        'my-medium-thumbnail' => __( 'My Medium Thumbnail (640px)', 'my-theme' ),
        'my-large-thumbnail'  => __( 'My Large Thumbnail (1024px)', 'my-theme' ),
    );
    return array_merge( $sizes, $custom_sizes );
}
add_filter( 'image_size_names_choose', 'my_responsive_image_sizes' );

add_image_size( 'my-small-thumbnail', 320, 9999 ); // 9999 表示高度不限制,保持原始比例
add_image_size( 'my-medium-thumbnail', 640, 9999 );
add_image_size( 'my-large-thumbnail', 1024, 9999 );

这个例子做了两件事:

  1. add_filter( 'image_size_names_choose', 'my_responsive_image_sizes' );: 这个过滤器允许你将自定义图片尺寸添加到 WordPress 后台的图片尺寸选择列表中。 my_responsive_image_sizes() 函数定义了一个包含三个响应式尺寸的数组,并将它们合并到现有的尺寸列表中。

  2. add_image_size(): 这三行代码分别定义了三个响应式尺寸:'my-small-thumbnail', 'my-medium-thumbnail', 'my-large-thumbnail'。 它们的宽度分别是 320px, 640px, 1024px,高度设置为 9999,表示高度不限制,保持原始比例。

在模板中使用:

$attachment_id = get_post_thumbnail_id(); // 获取文章特色图像的 ID

if ( wp_is_mobile() ) {
    $image_size = 'my-small-thumbnail';
} elseif ( wp_is_tablet() ) {
    $image_size = 'my-medium-thumbnail';
} else {
    $image_size = 'my-large-thumbnail';
}

$image_url = wp_get_attachment_image_src( $attachment_id, $image_size )[0];

echo '<img src="' . esc_url( $image_url ) . '" alt="' . get_the_title() . '">';

这段代码根据设备类型选择合适的图片尺寸,并显示相应的图片。

九、注意事项:性能优化和常见问题

  • 性能优化: 添加过多的自定义图片尺寸会增加服务器的负担,因为每次上传图片都需要生成多个尺寸的图片。 所以,只添加你真正需要的尺寸。

  • regenerate thumbnails: 在添加或修改图片尺寸后,你需要重新生成缩略图,才能使新的尺寸生效。 可以使用 "Regenerate Thumbnails" 等插件来完成这个任务。

  • 图片质量: 可以使用 wp_editor_set_quality 过滤器来调整图片质量。

  • 避免重复注册: add_image_size() 会检查是否已经存在同名的图片尺寸,避免重复注册。 但是,如果你在不同的地方多次调用 add_image_size(),可能会导致一些问题。 所以,最好将 add_image_size() 放在一个地方,例如主题的 functions.php 文件中。

十、总结:add_image_size() 的魔力

add_image_size() 函数是 WordPress 中一个非常重要的函数,它允许你轻松地自定义图片尺寸,从而更好地控制网站的图片显示效果。 通过深入理解 add_image_size() 的源码,你可以更好地利用它,并避免一些常见的问题。

希望今天的讲座对你有所帮助。 下次再见! (皮卡丘鞠躬)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注