Как я могу ускорить этот скрипт, я использую PHP GD
У меня проблемы со сценарием, который слишком долго генерировал миниатюры на ноутбуке моих друзей. Я выделил 2 ГБ памяти для сценария, вот "тесты".
- Перемещение файла заняло -0,101 минуты: 038.JPG
- Взял -4.638 для загрузки изображения в память и -6.093 для изменения размера: 038.JPG
- Взял -0,042, чтобы добавить информацию об изображении в базу данных!
- Перемещение файла заняло -0,054 минуты: 039.JPG
- Взял -4.670 для загрузки изображения в память и -5.720 для изменения размера: 039.JPG
- Взял -0,079, чтобы добавить информацию об изображении в базу данных! Взял -0.000 для перемещения и создания миниатюр всех файлов. Взял -24.619 для запуска всего скрипта.
Процессор: AMD E1-1200 - 1,40 ГГц. Память: 4,00 ГБ.
Ниже приведен PHP-скрипт (не самый чистый из кода), в основном он перемещает файлы из одной папки в другую, а также создает эскизы версий. В настоящее время я проверил это на 2 изображениях, но по моим расчетам, если бы я должен был сделать это для 100 изображений (что происходит в большинстве случаев), это займет около 25 минут, что недопустимо!
Изображения имеют разрешение 4512px x 3000px и имеют размер около 3,62 МБ.
<?php
session_start();
$run_start = microtime(true);
header("Cache-Control: no-cache, must-revalidate"); //HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); //Date in the past
//Make additional session keys
$_SESSION['ROOT_DIR'] = "http://".$_SERVER['HTTP_HOST']."/ppa/";
$_SESSION['ROOT_PATH'] = $_SERVER['DOCUMENT_ROOT']."/ppa/";
//Includes
include "../includes/db_connect.php";
include "../includes/required.php";
//$drive = $_POST['drive'];
$drive = $_GET['x'];
if (isset($drive)) {
$x = explode("_", $drive);
$x = $x[1];
//Need to connect to database to see which upload number this will be
if ($stmt = $mysqli->prepare("SELECT imageset FROM images WHERE udate = ? ORDER BY id DESC LIMIT 1")) {
$stmt->bind_param('s', $_SESSION['session_date']);
$stmt->execute(); //Execute the query
$stmt->store_result();
$stmt->bind_result($folder); //get variables from result
$stmt->fetch();
if ($stmt->num_rows != 1) { //result is returned
$folder = -1;
}
$folder = $folder+1;
//Set session variable for the progress bar
//$_SESSION['tmp'] = $x."_".$folder;
//Checks complete, now process the upload
$files = scandir($x.":/DCIM/");
// Identify directories
$source = $x.":/DCIM/";
$destination = $_SESSION['ROOT_PATH']."data/images/".str_replace("/","",$_SESSION['session_date'])."/".$folder."/";
if (count($files) > 2) {
//Create folders
if(!is_dir($_SESSION['ROOT_PATH']."data/images/".str_replace("/","",$_SESSION['session_date'])."/")) {
mkdir($_SESSION['ROOT_PATH']."data/images/".str_replace("/","",$_SESSION['session_date'])."/");}
if(!is_dir($_SESSION['ROOT_PATH']."data/images/".str_replace("/","",$_SESSION['session_date'])."/".$folder."/")) {
mkdir($_SESSION['ROOT_PATH']."data/images/".str_replace("/","",$_SESSION['session_date'])."/".$folder."/");}
if(!is_dir($_SESSION['ROOT_PATH']."data/images/".str_replace("/","",$_SESSION['session_date'])."/".$folder."/thumb/")) {
mkdir($_SESSION['ROOT_PATH']."data/images/".str_replace("/","",$_SESSION['session_date'])."/".$folder."/thumb/");}
// Delete all successfully-copied files
function delete($del) {
if (isset($del) && count($del) > 0) {
foreach ($del as $file) {
(!is_dir($file)) ? unlink($file) : "";
}
}
}
// Cycle through all source files
//Remove PHP time limites and memory limits to process high res photos
ini_set('memory_limit', '-1');
set_time_limit(0);
$move_resize = function($files,$source,$destination,$settings,$mysqli,$folder) {
foreach ($files as $file) {
if (in_array($file, array(".",".."))) continue;
//Check if the file is a directory
if (is_dir($source.$file)) {
//This is a directory
$new_dir[] = $file;
} else {
//Check that the filename isn't too long
if (strlen($file) > 100) {
$ext = explode(".",$file);
$tmp = str_split($file, (100-strlen($ext[1])-1));
$file = $tmp[0].".".$ext[1];
}
// If we copied this successfully, mark it for deletion
$move_start = microtime(true);
if (copy($source.$file, $destination.$file)) {
//allow all memory to be used, bad practice, but large photos need it!
$move_end = microtime(true);
echo "- Took ".number_format($move_start - $move_end,3)." minutes to move file: ".$file."<br />";
$loadintmem_start = microtime(true);
$im = imagecreatefromjpeg($source.$file);
$loadintmem_end = microtime(true);
//Create image thumbnail, width and height
$ratio = $settings['system']['thumb_size'] / imagesx($im);
$width = $settings['system']['thumb_size'];
$height = imagesy($im) * $ratio;
$thumb_start = microtime(true);
//Create thumbnail container
$thumb = imagecreatetruecolor($width,$height);
imagecopyresampled($thumb,$im,0,0,0,0,$width,$height,imagesx($im),imagesy($im));
imagejpeg($thumb,$destination."thumb/".$file);
//Free up memory
imagedestroy($im);
imagedestroy($thumb);
$thumb_end = microtime(true);
$delete[] = $source.$file; //Add to deletion list
echo "- - Took ".number_format($loadintmem_start - $loadintmem_end,3)." to load image into memory and ".number_format($thumb_start - $thumb_end,3)." to resize for: ".$file." <br />";
//Get additional image data
$udatetime = $_SESSION['session_date']." ".date('G:i:s');
$file_data = exif_read_data($source.$file);
$takendatetime = date("o/m/d G:i:s",$file_data['FileDateTime']);
//Add to database
$database_start = microtime(true);
$sql = "INSERT INTO images (jpg,udate,imageset,dodelete,sold,takendatetime,udatetime,venue) VALUES (?,?,?,?,?,?,?,?)";
$dodelete = 0; $sold = 0;
if($stmt = $mysqli->prepare($sql)) {
$stmt->bind_param('ssiiisss',$file,$_SESSION['session_date'],
$folder,$dodelete,$sold,$takendatetime,$udatetime,str_replace(" ","",strtolower($_SESSION['venue'])));
$stmt->execute();
$stmt->close();
} else {
echo "Unable to copy images (prepare failed) ".$mysqli->error;
}
$database_end = microtime(true);
echo "- - - Took ".number_format($database_start - $database_end,3)." to add image information to database! <br />";
}
}
}
return array($delete,$new_dir);
};
//Move images from main directory, then check for sub directories
$primary = $move_resize($files,$source,$destination,$settings,$mysqli,$folder);
//Phase results
$new_dir = $primary[1]; //Directories
$delete = $primary[0]; //Files to delete
delete($delete); //Delete files
unset($delete);
$proc_start = microtime(true);
if (count($new_dir) > 0) {
$directories = $new_dir; unset($new_dir);
foreach($directories as $current_dir) {
$files = scandir($x.":/DCIM/".$current_dir."/");
$source = $x.":/DCIM/".$current_dir."/";
if (count($files) > 0) {
$new = $move_resize($files,$source,$destination,$settings,$mysqli,$folder);
}
//Phase results
$delete = $new[0]; //Files to delete
//Enable subdirectory to be deleted
chmod($source, 755);
$delete[] = $source; //Add subdirectory to delete
delete($delete); //Delete files
unset($delete);
}
}
$proc_end = microtime(true);
echo "Took ".number_format($proc_start - $proc_end,3)." to move and create thumbnails of all files. <br />";
//Complete
//$_SESSION['tmp'] = "true";
//header("Location: ".$_SESSION['ROOT_DIR']."index.php?message=\"Upload complete!\"");
}
} else {
header("Location: ".$_SESSION['ROOT_DIR']."/php/search_drives.php?message=".$error);
$error = "Prepare failed: (".$mysqli->errno.") ".$mysqli->error;
}
}
$run_end = microtime(true);
echo "Took ".number_format($run_start - $run_end,3) ." to run entire script. <br />";
?>
Редактировать:
Собираясь попробовать ImageMaick, наконец-то удалось установить его после поиска dll-файла, который, я должен сказать, тупо трудно удержать...
По какой-то причине я получаю следующую ошибку:
Ошибка при создании эскиза: UnableToOpenBlob `032.JPG': нет такого файла или каталога @ error/blob.c/OpenBlob/2642
Вот некоторая информация, чтобы показать, что она установлена правильно:
Array
(
[GD Version] => bundled (2.1.0 compatible)
[FreeType Support] => 1
[FreeType Linkage] => with freetype
[T1Lib Support] =>
[GIF Read Support] => 1
[GIF Create Support] => 1
[JPEG Support] => 1
[PNG Support] => 1
[WBMP Support] => 1
[XPM Support] => 1
[XBM Support] => 1
[JIS-mapped Japanese Font Support] =>
)
И вот код, который я пытался создать миниатюру:
<?php
try {
$imagick = new Imagick();
$imagick->readImage('032.JPG');
$imagick->thumbnailImage(800, 800);
$imagick->writeImage('032(2).JPG');
}
catch(Exception $e) {
die('Error when creating a thumbnail: ' . $e->getMessage());
}
?>
Как вы можете видеть на скриншоте ниже, скрипт и изображение находятся в одном каталоге!