救命啊,PHP缩略图狂吃内存,怎么办

ERPshanghai 2009-12-02 04:44:58
我写了一个图片上传,并且生成缩略图的小程序,本以为就此万事大吉,没想到啊,实际使用中,图片文件一旦超过2M,缩略时内存使用量飙升,真的是飙升啊,一点都不夸张的。2M以内时使用内存才20M以内,大部分虚拟主机都能跑跑,一旦超越2M……比如说,3.5M大约要吃130M内存,5M内存使用量甚至到了290M!!
因为此程序主要是用于大图上传的,而且必须是后台生成缩略图,是冲印网站给普通用户用的。麻烦啊,用了几种缩略类,情况是一摸一样的,内存消耗降不下来。哪位有什么解决办法啊,万分感谢!

以下是我的代码:


---class/image.class.php---
<?php

class CreatMiniature
{
//公共变量
var $srcFile=""; //原图
var $echoType; //输出图片类型,link--不保存为文件;file--保存为文件
var $im=""; //临时变量
var $srcW=""; //原图宽
var $srcH=""; //原图高

//设置变量及初始化
function SetVar($srcFile,$echoType)
{
if (!file_exists($srcFile)){
echo '源图片文件不存在!';
exit();
}
$this->srcFile=$srcFile;
$this->echoType=$echoType;

$info = "";
$data = GetImageSize($this->srcFile,$info);
switch ($data[2])
{
case 1:
if(!function_exists("imagecreatefromgif")){
echo "你的GD库不能使用GIF格式的图片,请使用Jpeg或PNG格式!<a href='javascript:go(-1);'>返回</a>";
exit();
}
$this->im = ImageCreateFromGIF($this->srcFile);
break;
case 2:
if(!function_exists("imagecreatefromjpeg")){
echo "你的GD库不能使用jpeg格式的图片,请使用其它格式的图片!<a href='javascript:go(-1);'>返回</a>";
exit();
}
$this->im = ImageCreateFromJpeg($this->srcFile);
break;
case 3:
$this->im = ImageCreateFromPNG($this->srcFile);
break;
}
$this->srcW=ImageSX($this->im);
$this->srcH=ImageSY($this->im);
}

//生成扭曲型缩图
function Distortion($toFile,$toW,$toH)
{
$cImg=$this->CreatImage($this->im,$toW,$toH,0,0,0,0,$this->srcW,$this->srcH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}

//生成按比例缩放的缩图
function Prorate($toFile,$toW,$toH)
{
$toWH=$toW/$toH;
$srcWH=$this->srcW/$this->srcH;
if($toWH<=$srcWH)
{
$ftoW=$toW;
$ftoH=$ftoW*($this->srcH/$this->srcW);
}
else
{
$ftoH=$toH;
$ftoW=$ftoH*($this->srcW/$this->srcH);
}
if($this->srcW>$toW||$this->srcH>$toH)
{
$cImg=$this->CreatImage($this->im,$ftoW,$ftoH,0,0,0,0,$this->srcW,$this->srcH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
else
{
$cImg=$this->CreatImage($this->im,$this->srcW,$this->srcH,0,0,0,0,$this->srcW,$this->srcH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
}

//生成最小裁剪后的缩图
function Cut($toFile,$toW,$toH)
{
$toWH=$toW/$toH;
$srcWH=$this->srcW/$this->srcH;
if($toWH<=$srcWH)
{
$ctoH=$toH;
$ctoW=$ctoH*($this->srcW/$this->srcH);
}
else
{
$ctoW=$toW;
$ctoH=$ctoW*($this->srcH/$this->srcW);
}
$allImg=$this->CreatImage($this->im,$ctoW,$ctoH,0,0,0,0,$this->srcW,$this->srcH);
$cImg=$this->CreatImage($allImg,$toW,$toH,0,0,($ctoW-$toW)/2,($ctoH-$toH)/2,$toW,$toH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
ImageDestroy($allImg);
}

//生成背景填充的缩图
function BackFill($toFile,$toW,$toH,$bk1=255,$bk2=255,$bk3=255)
{
$toWH=$toW/$toH;
$srcWH=$this->srcW/$this->srcH;
if($toWH<=$srcWH)
{
$ftoW=$toW;
$ftoH=$ftoW*($this->srcH/$this->srcW);
}
else
{
$ftoH=$toH;
$ftoW=$ftoH*($this->srcW/$this->srcH);
}
if(function_exists("imagecreatetruecolor"))
{
@$cImg=ImageCreateTrueColor($toW,$toH);
if(!$cImg)
{
$cImg=ImageCreate($toW,$toH);
}
}
else
{
$cImg=ImageCreate($toW,$toH);
}
$backcolor = imagecolorallocate($cImg, $bk1, $bk2, $bk3); //填充的背景颜色
ImageFilledRectangle($cImg,0,0,$toW,$toH,$backcolor);
if($this->srcW>$toW||$this->srcH>$toH)
{
$proImg=$this->CreatImage($this->im,$ftoW,$ftoH,0,0,0,0,$this->srcW,$this->srcH);
if($ftoW<$toW)
{
ImageCopy($cImg,$proImg,($toW-$ftoW)/2,0,0,0,$ftoW,$ftoH);
}
else if($ftoH<$toH)
{
ImageCopy($cImg,$proImg,0,($toH-$ftoH)/2,0,0,$ftoW,$ftoH);
}
else
{
ImageCopy($cImg,$proImg,0,0,0,0,$ftoW,$ftoH);
}
}
else
{
ImageCopyMerge($cImg,$this->im,($toW-$ftoW)/2,($toH-$ftoH)/2,0,0,$ftoW,$ftoH,100);
}
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}


function CreatImage($img,$creatW,$creatH,$dstX,$dstY,$srcX,$srcY,$srcImgW,$srcImgH)
{
if(function_exists("imagecreatetruecolor"))
{
@$creatImg = ImageCreateTrueColor($creatW,$creatH);
if($creatImg)
ImageCopyResampled($creatImg,$img,$dstX,$dstY,$srcX,$srcY,$creatW,$creatH,$srcImgW,$srcImgH);
else
{
$creatImg=ImageCreate($creatW,$creatH);
ImageCopyResized($creatImg,$img,$dstX,$dstY,$srcX,$srcY,$creatW,$creatH,$srcImgW,$srcImgH);
}
}
else
{
$creatImg=ImageCreate($creatW,$creatH);
ImageCopyResized($creatImg,$img,$dstX,$dstY,$srcX,$srcY,$creatW,$creatH,$srcImgW,$srcImgH);
}
return $creatImg;
}

//输出图片,link---只输出,不保存文件。file--保存为文件
function EchoImage($img,$to_File)
{
switch($this->echoType)
{
case "link":
if(function_exists('imagejpeg')) return ImageJpeg($img);
else return ImagePNG($img);
break;
case "file":
if(function_exists('imagejpeg')) return ImageJpeg($img,$to_File);
else return ImagePNG($img,$to_File);
break;
}
}
}
?>




---class/miniature_memory.php---
<?php
function miniatureMemory($uploadfile){
$imageInfo = getimagesize($uploadfile);
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.8);

#echo $memoryNeeded;exit;

if (function_exists('memory_get_usage') && memory_get_usage() + $memoryNeeded > (integer) ini_get('memory_limit') * pow(1024, 2))
{
ini_set('memory_limit', (integer) ini_get('memory_limit') + ceil(((memory_get_usage() + $memoryNeeded) - (integer) ini_get('memory_limit') * pow(1024, 2)) / pow(1024, 2)) . 'M');
}
}
?>

...全文
555 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
ERPshanghai 2009-12-05
  • 打赏
  • 举报
回复
已经达到了客户要求,为什么不能理解?
目前换了主机后能满足之前设计的需求了
陈少鑫 2009-12-05
  • 打赏
  • 举报
回复
这也叫问题搞定啊????
客户能理解你们么????
ERPshanghai 2009-12-05
  • 打赏
  • 举报
回复
问题搞定,总结如下:

1、虚拟机会遇到很多问题,不仅是php.ini配置这么简单,还有虚拟机管理软件本身也有许多限制。

2、大容量图片的缩略处理,直接用GD库不是很方便,太多问题难以处理。GD库只在一般需求的情况下很方便。ImageMagick是否强一点目前尚不清楚,不过很感谢14楼提供的宝贵线索,值得我去研究。

3、phpThumb不好用,每次浏览都产生新的小图,太浪费资源,且每次重新生成缩略,这种模式不科学。基本无法满足正常商用。
songjgonline 2009-12-05
  • 打赏
  • 举报
回复
学习
alandy 2009-12-05
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 yjqstar 的回复:]
晕了,刚测试发现换了虚拟主机上,比本机测试更多了个问题:超过2.6M左右的文件,居然还无法上传!

http://www.posterjoy.com/phpinfo.php
这是环境配置,没发现什么问题啊,昨晚一怒之下把upload_max_filesize改到了200M!问题依旧,上传2.65M文件成功,上传2.88M文件失败!即使换成了FLASH上传,到了PHP处理部分就过不去了。move_uploaded_file失败。

没想到这么一个本以为很简单的问题,会困扰我这么久
[/Quote]
曾几何时,相同的处境,相同的感受~~
不过过了今天,明天再来看,这也是人生中不小的财富啊.
ERPshanghai 2009-12-05
  • 打赏
  • 举报
回复
晕了,刚测试发现换了虚拟主机上,比本机测试更多了个问题:超过2.6M左右的文件,居然还无法上传!

http://www.posterjoy.com/phpinfo.php
这是环境配置,没发现什么问题啊,昨晚一怒之下把upload_max_filesize改到了200M!问题依旧,上传2.65M文件成功,上传2.88M文件失败!即使换成了FLASH上传,到了PHP处理部分就过不去了。move_uploaded_file失败。

没想到这么一个本以为很简单的问题,会困扰我这么久
ERPshanghai 2009-12-04
  • 打赏
  • 举报
回复
这么多人支持ImageMagick?
问题是要服务器支持怎么办??
axiebin 2009-12-04
  • 打赏
  • 举报
回复
代码太长了!
ERPshanghai 2009-12-04
  • 打赏
  • 举报
回复
跟客户签的合同一再延期了,唉。
不是不能装ImageMagick,问题是给他的是虚拟主机,装那玩意BOSS也不会同意的!
可是又答应过客户要提供这么大图片的预览功能,难道看全图?估计要死翘翘了
ERPshanghai 2009-12-04
  • 打赏
  • 举报
回复
后天,我必须要完成这个了,难道ImageMagick是唯一选择了吗?难道GD真的这么没用,PHP5才出的GD2啊,PHP不是说很强悍吗?为什么我一会做个文件上传进度条不行,一会做个缩略图就这么多问题?
alandy 2009-12-04
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 yjqstar 的回复:]
这么多人支持ImageMagick?
问题是要服务器支持怎么办??
[/Quote]
虚拟机基本上你就别指望了,建议公司自己买台服务器了,爱装啥装啥。
ERPshanghai 2009-12-04
  • 打赏
  • 举报
回复
经实测,phpThumb比我这个更难支持大图……
thirdapple 2009-12-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 xuzuning 的回复:]
用GD肯定是无法解决的,因为它需要将图片解压成位图才能处理
[/Quote]
绝对不是这个原因。
2m的jpeg大概也就3k*2k左右大,也就18m的样子。就算是gd的bug也不会是因为“将图片解压成位图“这个原因。纯粹在误人子弟。换imagick试。
LuciferStar 2009-12-03
  • 打赏
  • 举报
回复
建议不要用类。
wontao 2009-12-03
  • 打赏
  • 举报
回复
做个记号
tfxg 2009-12-03
  • 打赏
  • 举报
回复
看不完代碼
Siramizu 2009-12-03
  • 打赏
  • 举报
回复
ImageMagick +2
不过要服务器支持
yctin 2009-12-03
  • 打赏
  • 举报
回复
ImageMagick +1
alandy 2009-12-03
  • 打赏
  • 举报
回复
速去学习ImageMagick.我现在一台服务器用ImageMagick每天处理2W张从3M~20M原图,然后生成六种规格缩略图。
安安_007 2009-12-03
  • 打赏
  • 举报
回复
路过!!!
加载更多回复(11)

20,397

社区成员

发帖
与我相关
我的任务
社区描述
“超文本预处理器”,是在服务器端执行的脚本语言,尤其适用于Web开发并可嵌入HTML中。PHP语法利用了C、Java和Perl,该语言的主要目标是允许web开发人员快速编写动态网页。
phpphpstorm 技术论坛(原bbs)
社区管理员
  • 开源资源社区
  • phpstory
  • xuzuning
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧