Modificare il rapporto d'aspetto di tutte le immagini dentro una cartella

  • 14 Dic 2014
  • PHP, convert

Scenario

Abbiamo dentro una cartella un numero quasi infinito d'immagini di diverse dimensioni e diversi rapporti d'aspetto (aspect ratio). Si vuole modificare le dimensioni di ogni immagine (crop) a fin di aggiustarle ad un rapporto d'aspetto determinato.

Soluzione

Uno script in PHP che prende le dimensioni dell'immagine originale, calcola quanto tagliare in base al rapporto d'aspetto indicato e crea una copia dell'immagine con le nuove dimensioni. Per eseguire questo script in consola, è necessario aggiungere #!/usr/bin/php alla prima riga.

<?php

if (count($_SERVER['argv']) < 3) {
  print "Usage\n";
  print "  " . $_SERVER['SCRIPT_FILENAME'] . " input output ratio\n";
  exit();
}

define("DIR",$_SERVER['argv'][1]);
define("DIROUT",$_SERVER['argv'][2]);
define("RATIO",$_SERVER['argv'][3]);

$input = realpath(DIR);
$output = realpath(DIROUT);

$fraction = explode("/", RATIO);
if (count($fraction) == 1) {
  $ratio = RATIO;
} else {
  $ratio = $fraction[0]/$fraction[1];
}

print $ratio."\n";

if (!$handle = opendir($input)) {
  print "Can't open input directory: " . DIR . "\n";
  return;
}

$objects = new RecursiveIteratorIterator(
  new RecursiveDirectoryIterator($input), 
  RecursiveIteratorIterator::SELF_FIRST
);

foreach ($objects as $file => $object) {

  // handle only jpg files
  if (pathinfo($file, PATHINFO_EXTENSION) != 'jpg') {
    continue;
  }

  // get image size
  $img_info = array();
  exec("convert " . escapeshellarg($file) . " -print \"%w,%h\" /dev/null", $img_info);
  $img_size = explode(",", $img_info[0]);
  $img_w = $img_size[0];
  $img_h = $img_size[1];

  // tall or wide?
  if ($img_w >= $img_h) {
    $img_ratio = $img_w/$img_h;
    $min = "img_h";
    $max = "img_w";
  } else {
    $img_ratio = $img_h/$img_w;
    $min = "img_w";
    $max = "img_h";
  }

  // crop and offset
  if ($img_ratio < $ratio) {
    $var = "new_".$max;
    $$var = $$max;

    $var2 = "new_".$min;
    $$var2 = round($$var/$ratio);
  } else {
    $var = "new_".$min;
    $$var = $$min;

    $var_new_max = "new_".$max;
    $$var_new_max = round($$var*$ratio);
  }

  // create output directory
  $output_path = $output . substr($file, strlen($input));
  if (!file_exists(dirname($output_path))) { 
    mkdir(dirname($output_path));
  }

  $cmd  = "convert -quality 90 " . escapeshellarg($file);
  $cmd .= " -crop {$new_img_w}x{$new_img_h}+";
  $cmd .= abs(floor((intval($img_w) - intval($new_img_w)) / 2)). "+";
  $cmd .= floor((intval($img_h) - intval($new_img_h)) / 2);
  $cmd .= " +repage " . escapeshellarg($output_path);

  print "\nconvert " . pathinfo($file,  PATHINFO_BASENAME). "\n";
  print "  from: {$img_w} x {$img_h}\n";
  print "    to: {$new_img_w} x {$new_img_h}\n";

  exec($cmd);

}

closedir($handle);

Utilizzo

Per modificare il rapporto d'aspetto in 16/9 dell'immagini dentro la cartella input e salvare il risultato nella cartella output

./script.php input output 16/9