使用 PHP 和 ImageMagick 递归调整大小和命名图像时,如何根据现有文件名和扩展名最好地编写新文件
When using PHP and ImageMagick to resize and name images recursively, how to best write new files based on the existing filename and extension
我有一个包含 'source' 个图像的目录,我正在保存多个调整大小的文件。我希望给定目录中的所有 jpg 和 png 文件都根据其原始文件名(la filename-small.jpg、filename-medium.jpg 等)调整大小并使用新名称保存。我正在使用 ImageMagick。
在 SO 上的另一个问题中找到了获取所有文件的正则表达式,并且有所帮助——但我并不完全明白这里发生了什么。
我目前所拥有的是将原始文件扩展名放在文件名中间。虽然我明白为什么会这样,但我不确定解决此问题的最佳方法。
我怎样才能把它变成 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);
}
}
内森,
您正在使用括号捕获该扩展名。您想要捕获文件名,而不仅仅是扩展名。您可以使用非大括号 ((?:)
) 对扩展变体进行分组。
$images = new RegexIterator($iterator, '/^(.+)\.(?:jpe?g|png)$/i', RecursiveRegexIterator::GET_MATCH);
我还在扩展名之前转义了文字点 (.
)。
或者,您可以从 $image
变量中拆分扩展名和文件名:
preg_match('/^(.+)\.([^.]+)$/', $image, $matches);
// Set the original filename w/o the extension
$originalFilename = $matches[1];
// Set the original extension
$originalExtension = $matches[2];
最后,FWIW,如果我要这样做,我不会使用 RegexIterator
,而是只是迭代目录,只对每个文件名使用 preg_match
。
$directory = dir('source/assets/uploads/test');
while(false !== ($entry = $directory->read())) {
$result = preg_match('/^(.+)\.(jpe?g|png)$/i', $entry, $matches);
if($result === false) {
die('ERROR: `preg_match` failed on '.$entry);
} else if($result === 0) {
// not an image file
continue;
}
// Set the original filename w/o the extension
$originalFilename = $matches[1];
// Set the original extension
$originalExtension = $matches[2];
// ... do the other things on the file
}
参考文献:
编辑:
对于 $matches
内的命名引用,您可以使用此修改后的正则表达式:
preg_match('/^(?P<filename>.+)\.(?P<extension>jpe?g|png)$/i', $entry, $matches);
?P<key>
是一个“占位符”,它将 key
指定为对该匹配项的引用。
您仍将 $matches
作为数组返回,而不是对象,但随后您可以使用该占位符作为索引访问值。
// Set the original filename w/o the extension
$originalFilename = $matches['filename'];
// Set the original extension
$originalExtension = $matches['extension'];
FWIW,数字索引也仍然存在。
我有一个包含 'source' 个图像的目录,我正在保存多个调整大小的文件。我希望给定目录中的所有 jpg 和 png 文件都根据其原始文件名(la filename-small.jpg、filename-medium.jpg 等)调整大小并使用新名称保存。我正在使用 ImageMagick。
在 SO 上的另一个问题中找到了获取所有文件的正则表达式,并且有所帮助——但我并不完全明白这里发生了什么。
我目前所拥有的是将原始文件扩展名放在文件名中间。虽然我明白为什么会这样,但我不确定解决此问题的最佳方法。
我怎样才能把它变成 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);
}
}
内森,
您正在使用括号捕获该扩展名。您想要捕获文件名,而不仅仅是扩展名。您可以使用非大括号 ((?:)
) 对扩展变体进行分组。
$images = new RegexIterator($iterator, '/^(.+)\.(?:jpe?g|png)$/i', RecursiveRegexIterator::GET_MATCH);
我还在扩展名之前转义了文字点 (.
)。
或者,您可以从 $image
变量中拆分扩展名和文件名:
preg_match('/^(.+)\.([^.]+)$/', $image, $matches);
// Set the original filename w/o the extension
$originalFilename = $matches[1];
// Set the original extension
$originalExtension = $matches[2];
最后,FWIW,如果我要这样做,我不会使用 RegexIterator
,而是只是迭代目录,只对每个文件名使用 preg_match
。
$directory = dir('source/assets/uploads/test');
while(false !== ($entry = $directory->read())) {
$result = preg_match('/^(.+)\.(jpe?g|png)$/i', $entry, $matches);
if($result === false) {
die('ERROR: `preg_match` failed on '.$entry);
} else if($result === 0) {
// not an image file
continue;
}
// Set the original filename w/o the extension
$originalFilename = $matches[1];
// Set the original extension
$originalExtension = $matches[2];
// ... do the other things on the file
}
参考文献:
编辑:
对于 $matches
内的命名引用,您可以使用此修改后的正则表达式:
preg_match('/^(?P<filename>.+)\.(?P<extension>jpe?g|png)$/i', $entry, $matches);
?P<key>
是一个“占位符”,它将 key
指定为对该匹配项的引用。
您仍将 $matches
作为数组返回,而不是对象,但随后您可以使用该占位符作为索引访问值。
// Set the original filename w/o the extension
$originalFilename = $matches['filename'];
// Set the original extension
$originalExtension = $matches['extension'];
FWIW,数字索引也仍然存在。