Skip to content

Instantly share code, notes, and snippets.

@felipelavinz
Created July 19, 2013 04:18
Show Gist options
  • Save felipelavinz/6035203 to your computer and use it in GitHub Desktop.
Save felipelavinz/6035203 to your computer and use it in GitHub Desktop.
Create image thumbnails with PHP and Imagick
<?php
$abs_start = microtime(true);
$path = __DIR__;
$Directory = new RecursiveDirectoryIterator('.');
$img_extensions = array('jpg', 'jpeg', 'gif', 'png');
$desired_sizes = array(
'300x300',
'800x450',
'220x260',
'125x80',
'340x220',
'365x255',
'660x430',
'940x345',
'940x450',
'960x960'
);
foreach ( new RecursiveIteratorIterator($Directory) as $filename => $file ){
if ( $file->isDir() )
continue;
$fullpath = $file->getPathName();
$path = pathinfo( $fullpath, PATHINFO_DIRNAME );
$filename = pathinfo( $fullpath, PATHINFO_BASENAME );
$extension = strtolower(pathinfo( $fullpath, PATHINFO_EXTENSION ));
$noext = str_replace( '.'. $extension, '', $filename );
// si no es imagen, chao pescao
if ( ! in_array($extension, $img_extensions) )
continue;
$parts = explode( '-', str_replace( '.'.$extension, '', $filename) );
if ( $parts > 1 ) {
$maybe_size = end($parts);
$matches = array();
if ( preg_match('/([0-9]{1,4})(x){1}([0-9]{1,4})/', $maybe_size, $matches) === 1 ){
// print_r($matches);
// unlink( $fullpath );
continue;
} else {
echo $fullpath."\n";
}
}
// continue;
$start = microtime(true);
$image_size = getimagesize( $fullpath );
list($w, $h) = $image_size;
foreach ( $desired_sizes as $size ){
$image = new Imagick( $fullpath );
$dimensions = explode('x', $size);
$crop = $size === '960x960' ? false : true;
list( $dw, $dh ) = $dimensions;
$dims = image_resize_dimensions( $w, $h, $dw, $dh, $crop );
list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
if ( $crop ) {
$image->cropThumbnailImage( $dw, $dh );
// $image->cropImage( $src_w, $src_h, $src_x, $src_y );
// $image->setImagePage( $src_w, $src_h, 0, 0);
// if ( $dst_w || $dst_h ) {
// // If destination width/height isn't specified, use same as
// // width/height from source.
// if ( ! $dst_w )
// $dst_w = $src_w;
// if ( ! $dst_h )
// $dst_h = $src_h;
// $image->scaleImage( $dst_w, $dst_h );
// } else {
// $size = $image->getImageGeometry();
// }
}
$dest_filename = "{$path}/{$noext}-{$size}.{$extension}";
echo $dest_filename ."\n";
$image->writeImage( $dest_filename );
unset($image);
}
echo 'hecho en: '. ( microtime(true) - $start ) .' segundos'."\n";
echo '---'."\n";
}
echo 'TIEMPO TOTAL: '. ( microtime(true) - $abs_start ) .' segundos'."\n";
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;
if ( $crop ) {
// crop the largest possible portion of the original image that we can size to $dest_w x $dest_h
$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 = intval($new_h * $aspect_ratio);
}
if ( !$new_h ) {
$new_h = intval($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);
$s_x = floor( ($orig_w - $crop_w) / 2 );
$s_y = floor( ($orig_h - $crop_h) / 2 );
} else {
// don't crop, just 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 the resulting image would be the same size or larger we don't want to resize it
if ( $new_w >= $orig_w && $new_h >= $orig_h )
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 );
}
function wp_constrain_dimensions( $current_width, $current_height, $max_width=0, $max_height=0 ) {
if ( !$max_width and !$max_height )
return array( $current_width, $current_height );
$width_ratio = $height_ratio = 1.0;
$did_width = $did_height = false;
if ( $max_width > 0 && $current_width > 0 && $current_width > $max_width ) {
$width_ratio = $max_width / $current_width;
$did_width = true;
}
if ( $max_height > 0 && $current_height > 0 && $current_height > $max_height ) {
$height_ratio = $max_height / $current_height;
$did_height = true;
}
// Calculate the larger/smaller ratios
$smaller_ratio = min( $width_ratio, $height_ratio );
$larger_ratio = max( $width_ratio, $height_ratio );
if ( intval( $current_width * $larger_ratio ) > $max_width || intval( $current_height * $larger_ratio ) > $max_height )
// The larger ratio is too big. It would result in an overflow.
$ratio = $smaller_ratio;
else
// The larger ratio fits, and is likely to be a more "snug" fit.
$ratio = $larger_ratio;
$w = intval( $current_width * $ratio );
$h = intval( $current_height * $ratio );
// Sometimes, due to rounding, we'll end up with a result like this: 465x700 in a 177x177 box is 117x176... a pixel short
// We also have issues with recursive calls resulting in an ever-changing result. Constraining to the result of a constraint should yield the original result.
// Thus we look for dimensions that are one pixel shy of the max value and bump them up
if ( $did_width && $w == $max_width - 1 )
$w = $max_width; // Round it up
if ( $did_height && $h == $max_height - 1 )
$h = $max_height; // Round it up
return array( $w, $h );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment