Issue
I've got a directory of 'source' images that I'm saving out multiple resized files. I'd like all jpg and png files in a given directory to be resized and saved with new names based on their original file names (a la filename-small.jpg, filename-medium.jpg, etc.) I'm using ImageMagick.
The regex stuff to get all the files was found in another question here on SO and has helped—but I don't totally get what all is going on here.
What I have currently plops the original file extension in the middle of the file name. While I understand why this is happening, I'm not sure the best approach to fix this.
How can I get this to to be filename-large.jpg instead of filename.jpg-large.jpg?
Here is what I have currently:
<?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);
}
}
Solution
Nathan,
You are capturing that extension with the parens. You want to capture the file name, not just the extension. You can use non-caputring parens ((?:)
) for grouping the extension variations.
$images = new RegexIterator($iterator, '/^(.+)\.(?:jpe?g|png)$/i', RecursiveRegexIterator::GET_MATCH);
I also escaped the literal dots (.
) before the extensions.
Alternatively, you could just split up the extension and filename from the $image
variable:
preg_match('/^(.+)\.([^.]+)$/', $image, $matches);
// Set the original filename w/o the extension
$originalFilename = $matches[1];
// Set the original extension
$originalExtension = $matches[2];
Lastly, FWIW, were I to do this I would not use the RegexIterator
but tather just iterate the directory and just use preg_match
only on each filename.
$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
}
Refs:
EDIT:
For named references inside of $matches
you can use this modified regexp:
preg_match('/^(?P<filename>.+)\.(?P<extension>jpe?g|png)$/i', $entry, $matches);
The ?P<key>
is a "placeholder" that assigns key
as a reference to that caputred match.
You are still going to get $matches
back as an array, not an object, but then you can access the values with that placeholder as the index.
// Set the original filename w/o the extension
$originalFilename = $matches['filename'];
// Set the original extension
$originalExtension = $matches['extension'];
FWIW, the numeric indexes are still there too.
Answered By - Karl Wilbur Answer Checked By - Dawn Plyler (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.