我有一个大型mysql表,表中有超过1200000行的innoDB格式的原始图像(每个图像一行),但我将处理大约600000行。我想快速做的是从数据库中检索本地图像文件名,确定其大小和维度,然后将详细信息存储回数据库中。
在没有图像计算的情况下对数据库执行I/O很快,因为我已经优化配置了mysql设置。事实上,我配置了一个缓冲区,使其大于最大mysql数据库文件大小的整个大小。
目前,我计算图像尺寸和大小的代码是:
$img='/path/to/current/image/to/find/dimensions/for.jpg';
$ifs=-1;
$iw=-1;
$ih=-1;
if ($ifs=@filesize($img)){
$im=NULL;
$im=@imagecreatefromjpeg($img);
if ($im){
$iw=imagesx($im);
$ih=imagesy($im);
imagedestroy($im);
}
$im=NULL;
}
有没有一种方法可以将这些代码转换为一种执行时间大大减少的格式?
记住。我处理的是本地映像,上面的代码正在执行600000次,所以优化在这里很重要,任何能为我节省一毫秒执行时间的代码都会受到赞赏。
所有有问题的图像都是jpeg格式,大小通常在600x400px到800x533px 之间
有什么想法吗?
在getimagesize()的文档中,php.net上有一条用户注释,它没有读取整个jpeg文件来查找维度,因为维度存储在文件的头部之后。该代码特定于jpeg,不能用于其他文件类型。
这个代码应该比你的更快,因为它不会读取整个文件,也不会从中创建资源
<?php
// Retrieve JPEG width and height without downloading/reading entire image.
function getjpegsize($img_loc) {
$handle = fopen($img_loc, "rb") or die("Invalid file stream.");
$new_block = NULL;
if(!feof($handle)) {
$new_block = fread($handle, 32);
$i = 0;
if($new_block[$i]=="xFF" && $new_block[$i+1]=="xD8" && $new_block[$i+2]=="xFF" && $new_block[$i+3]=="xE0") {
$i += 4;
if($new_block[$i+2]=="x4A" && $new_block[$i+3]=="x46" && $new_block[$i+4]=="x49" && $new_block[$i+5]=="x46" && $new_block[$i+6]=="x00") {
// Read block size and skip ahead to begin cycling through blocks in search of SOF marker
$block_size = unpack("H*", $new_block[$i] . $new_block[$i+1]);
$block_size = hexdec($block_size[1]);
while(!feof($handle)) {
$i += $block_size;
$new_block .= fread($handle, $block_size);
if($new_block[$i]=="xFF") {
// New block detected, check for SOF marker
$sof_marker = array("xC0", "xC1", "xC2", "xC3", "xC5", "xC6", "xC7", "xC8", "xC9", "xCA", "xCB", "xCD", "xCE", "xCF");
if(in_array($new_block[$i+1], $sof_marker)) {
// SOF marker detected. Width and height information is contained in bytes 4-7 after this byte.
$size_data = $new_block[$i+2] . $new_block[$i+3] . $new_block[$i+4] . $new_block[$i+5] . $new_block[$i+6] . $new_block[$i+7] . $new_block[$i+8];
$unpacked = unpack("H*", $size_data);
$unpacked = $unpacked[1];
$height = hexdec($unpacked[6] . $unpacked[7] . $unpacked[8] . $unpacked[9]);
$width = hexdec($unpacked[10] . $unpacked[11] . $unpacked[12] . $unpacked[13]);
return array($width, $height);
} else {
// Skip block marker and read block size
$i += 2;
$block_size = unpack("H*", $new_block[$i] . $new_block[$i+1]);
$block_size = hexdec($block_size[1]);
}
} else {
return FALSE;
}
}
}
}
}
return FALSE;
}
?>
我以前使用过这个JPEG大小的代码,它实际上可能是基于另一个答案中发布的代码!
准备好的语句将节省数据库插入的大量开销。
#!/usr/bin/env php
<?php
$db = new PDO("mysql:host=localhost;dbname=images", "username", "password");
$images = $db->query("SELECT id, filename FROM images", PDO::FETCH_NUM);
$stmt = $db->prepare("INSERT INTO images SET width = ?, height = ? WHERE id = ?");
foreach ($images as $image) {
list($w, $h) = jpgsize($image[1]);
$stmt->execute(array($w, $h, $image[0]));
}
$db->close();
function jpgsize($img) {
$h = fopen($img, "rb") or return false;
$block = null;
if(feof($h)) {
fclose($h);
return false;
}
$block = fread($h, 32);
if (substr($block, 0, 4) === "xFFxD8xFFxE0" && substr($block, 6, 5) === "x4Ax46x49x46x00") {
$block_size = unpack("H*", substr($block, 4, 2));
$block_size = hexdec($block_size[1]);
$i = 4;
while(!feof($h)) {
$i += $block_size;
$block .= fread($h, $block_size);
if(substr($block, $i, 1) === "xFF") {
$sof_marker = array("xC0", "xC1", "xC2", "xC3", "xC5", "xC6", "xC7", "xC8", "xC9", "xCA", "xCB", "xCD", "xCE", "xCF");
if(in_array(substr($block, $i+1, 1), $sof_marker)) {
$size_data = substr($block, $i + 2, 7);
$unpacked = unpack("H*", $size_data);
$unpacked = $unpacked[1];
$height = hexdec(substr($unpacked, 6, 4));
$width = hexdec(substr($unpacked, 10, 4));
fclose($h);
return array($width, $height);
} else {
$i += 2;
$block_size = unpack("H*", substr($block, $i, 2));
$block_size = hexdec($block_size[1]);
}
} else {
fclose($h);
return false;
}
}
}
fclose($h);
return false;
}