当使用PHP和ImageMagick递归地调整图像大小和命名图像时,如何最好地基于现有文件名和扩展名编写新文件

当使用PHP和ImageMagick递归地调整图像大小和命名图像时,如何最好地基于现有文件名和扩展名编写新文件,php,regex,imagemagick,imagick,Php,Regex,Imagemagick,Imagick,我有一个“源”图像目录,我正在保存多个调整大小的文件。我希望给定目录中的所有jpg和png文件都能根据它们的原始文件名(la filename-small.jpg、filename-medium.jpg等)调整大小并使用新名称保存。我正在使用ImageMagick 在这里的另一个问题中发现了用于获取所有文件的regex文件,这对我很有帮助,但我并不完全了解这里到底发生了什么 我目前在文件名中间使用原始文件扩展名。虽然我理解为什么会发生这种情况,但我不确定解决这一问题的最佳方法 如何将文件名改为f

我有一个“源”图像目录,我正在保存多个调整大小的文件。我希望给定目录中的所有jpg和png文件都能根据它们的原始文件名(la filename-small.jpg、filename-medium.jpg等)调整大小并使用新名称保存。我正在使用ImageMagick

在这里的另一个问题中发现了用于获取所有文件的regex文件,这对我很有帮助,但我并不完全了解这里到底发生了什么

我目前在文件名中间使用原始文件扩展名。虽然我理解为什么会发生这种情况,但我不确定解决这一问题的最佳方法

如何将文件名改为filename-large.jpg而不是filename.jpg-large.jpg

以下是我目前的情况:

<?php

    $directory = new RecursiveDirectoryIterator('source/assets/uploads/test');
    $iterator = new RecursiveIteratorIterator($directory);
    $images = new RegexIterator($iterator, '/^.+(.jpe?g|.png)$/i', RecursiveRegexIterator::GET_MATCH);

    $widths = [
        'small' => 400,
        'medium' => 800,
        'large' => 1000,
        'xlarge' => 1600,
    ];
    
    foreach($images as $image => $value) {

        // Set the original filename w/o the extension
        $originalFilename = $image;

        // set the extension based on the original
        // ideally conform the extension jpeg to jpg
        $originalExtension = '.jpg';
        
        // create a new Imagick instance
        $newImage = new Imagick($image);

        // strip out some junk
        $newImage->stripImage();

        // write a new file for each width 
        // and name it based on the original filename
        foreach ($widths as $key => $value) {
            // using 0 in the second $arg will keep the same image ratio
            $newImage->resizeImage($value,0, imagick::FILTER_LANCZOS, 0.9);
            $newImage->writeImage($originalFilename . '-' . $key . $originalExtension);
        }
    }
内森

您正在使用parens捕获该扩展。您希望捕获文件名,而不仅仅是扩展名。您可以使用非caputring参数(
(?:)
)对扩展变量进行分组

$images=newregexiterator($iterator,'/^(+)\.(?:jpe?g|png)$/i',RecursiveRegexIterator::GET_MATCH);
我还转义了扩展之前的文字点(

或者,您可以从
$image
变量中拆分扩展名和文件名:

preg\u match('/^(+)\.([^.]+)$/',$image,$matches);
//设置不带扩展名的原始文件名
$originalFilename=$matches[1];
//设置原始扩展名
$originalExtension=$matches[2];
最后,FWIW,如果我这样做,我不会使用
RegexIterator
,但tather只是迭代目录,只对每个文件名使用
preg_match

$directory=dir('source/assets/uploads/test');
while(false!==($entry=$directory->read()){
$result=preg_match('/^(+)\(jpe?g|png)$/i',$entry,$matches);
如果($result==false){
die('ERROR:'preg_match`在'.$entry'上失败);
}else if($result==0){
//不是图像文件
继续;
}
//设置不带扩展名的原始文件名
$originalFilename=$matches[1];
//设置原始扩展名
$originalExtension=$matches[2];
//…做文件上的其他事情
}
参考文献:

编辑: 对于
$matches
中的命名引用,可以使用此修改的regexp:

preg_match('/^(?P.+)\.(?Pjpe?g|png)$/i',$entry,$matches);
?p
是一个“占位符”,它指定
键作为对该caputred匹配的引用

您仍然可以将
$matches
作为数组而不是对象返回,但是您可以使用该占位符作为索引来访问这些值

//设置不带扩展名的原始文件名
$originalFilename=$matches['filename'];
//设置原始扩展名
$originalExtension=$matches['extension'];

FWIW,数字索引也仍然存在。

尝试
/^.+\(?模式,以排除所有带有
$width
后缀的限定字符串。或者,
/^(.+)(?:-(?:small | x?large | medium))。(?:jpe?g | png)$/i
@WiktorStribiżew我喜欢它的发展方向这可能有助于将来在repo中添加新图像时,我只想更新这些图像。但是,我也看到希望将“large”更新为1200。也许从长远来看,只根据图像大小值而不是抽象键命名文件会更好。如果我如果需要一个新的大小,添加它将不会有太大问题。这非常有帮助,谢谢!为了让我没有经验的编程大脑更清楚地了解这一点,是否有可能以更关键/值类型的方式捕获数组中的数据?因此,与$matches[2]不同,类似于$matches->extension?