几年前,我创作了一个
PHP(ZEND)模块,我今天在一些项目中仍然使用它.这个模块是基于对PHP图像处理的相当基本的(即copypasta)理解而构建的,但在一种情况下工作得很漂亮.
模块从表中提取blob数据,将其解析为图像,使用imagcopyresampled()调整其大小,然后将生成的.jpg发送到浏览器,它被称为标准控制器操作.
它似乎适用于所有情况,除非用户从Facebook保存原始图像(即右键单击Facebook图像查看器并下载到桌面然后上传到客户端站点).我自己测试了很多次并且能够复制它.我还能够通过photoshop重新保存时上传相同的图像,而不会遇到问题.
我怀疑facebook图像显示在文件中添加了一些导致我的系统中断的额外元数据.
这有解决方案吗?
private function _buildImage($mode) { //Prepare the output image //Currently CROP and RESIZE are using different output onstruction calls //So $finalImage is initialized prior to entering the mode blocks. $finalImage = imagecreatetruecolor($this->_width,$this->_height); $backgroundFillColor = imagecolorallocate($finalImage,RED,BLUE,GREEN); imageFill($finalImage,$backgroundFillColor); $this->_table = $this->_getTable($mode); $image = $this->_request->image; $this->_imageData = $this->_table->fetchEntryAsRow($image); //Set top and left to 0 to capture the top/left corner of the orignal image. $top = 0; $left = 0; $inputimage = imagecreatefromstring( $this->_imageData->image); list($inputWidth,$inputHeight) = $this->_getimageSize($this->_imageData->image); //Ratio is the target ratio of $this->_width divided by $this->_height,as set in actions. //For index thumbnails this ratio is .7 //For index large images this ratio is 2 $ratio = $this->_width / $this->_height; //define offset width and offset height as being equal to input image width and height $offsetWidth = $inputWidth; $offsetHeight = $inputHeight; //Define Original Ratio as found in the image in the table. $inputRatio = $inputWidth / $inputHeight; //Rendering maths for RESIZE and CROP modes. //RESIZE forces the whole input image to appear within the frame of the output image. //CROP forces the output image to contain only the relevantly sized piece of the input image,measured from the middle. if($this->_mode == CROP) { if($inputRatio > $ratio) { //Original image is too wide,use $height as is. Modify $width; //define $scale: input is scaled to output along height. $scale = $inputHeight / $this->_height; //Calculate $left: an integer calculated based on 1/2 of the input width * half of the difference in the rations. $left = round(($inputWidth/2)*(($inputRatio-$ratio)/2),0); $inputWidth = round(($inputWidth - ($left*2)),0); $offset = $offsetWidth - $inputWidth; } else { //Original image is too high,use $width as is. Modify $height; $scale = $inputWidth / $this->_width; $inputHeight = round(($this->_height * $scale),0); $offset = $offsetHeight - $inputHeight; $top = $offset / 2; } imagecopyresampled($finalImage,//Destination Image $inputimage,//Original Image 0,//Destination top left Coord $left,$top,//Source top left coord $this->_width,$this->_height,//Final location Bottom Right Coord $inputWidth,$inputHeight //Source bottom right coord. ); } else { if($inputRatio < $ratio) { //Original image is too wide,use $height as is. Modify $width; $scale = $inputHeight / $this->_height; $calculatedWidth = round(($inputWidth / $scale),0); $calculatedHeight = $this->_height; $offset = $this->_width - $calculatedWidth; $left = round(($offset / 2),0); $top = 0; } else { //Original image is too high,use $width as is. Modify $height; $scale = $inputWidth / $this->_width; $calculatedHeight = round(($inputHeight / $scale),0); $calculatedWidth = $this->_width; $offset = $this->_height - $calculatedHeight; $top = round(($offset / 2),2); } imagecopyresampled($finalImage,//Original Image $left,//Destination top left Coord 0,//Source top left coord $calculatedWidth,$calculatedHeight,$inputHeight //Source bottom right coord. ); } imagejpeg($finalImage,null,100); imagedestroy($inputimage); imagedestroy($finalImage); }
我怀疑问题实际上可能与_getimageSize的实现有关.
private function _getimageSize($data) { $soi = unpack('nmagic/nmarker',$data); if ($soi['magic'] != 0xFFD8) return false; $marker = $soi['marker']; $data = substr($data,4); $done = false; while(1) { if (strlen($data) === 0) return false; switch($marker) { case 0xFFC0: $info = unpack('nlength/Cprecision/nY/nX',$data); return array($info['X'],$info['Y']); break; default: $info = unpack('nlength',$data); $data = substr($data,$info['length']); $info = unpack('nmarker',$data); $marker = $info['marker']; $data = substr($data,2); break; } } }
您可以在http://www.angelaryan.com/gallery/Image/22看到此问题的另一个示例,该示例显示蓝色方块,而不是存储在数据库中的图像.