2013-07-27 33 views
5

Một vài năm trước, tôi đã viết một mô-đun PHP (ZEND) mà tôi vẫn sử dụng ngày hôm nay trong một số dự án của mình. Mô-đun này được xây dựng với sự hiểu biết khá thô sơ (ví dụ: copypasta) về thao tác hình ảnh PHP nhưng hoạt động đẹp ngoại trừ trong một trường hợp.Tại sao PHP không tạo ra hình ảnh khi tải hình ảnh đã được chụp từ facebook?

Mô-đun lấy dữ liệu blob từ bảng, phân tích dữ liệu đó thành hình ảnh, sử dụng imagcopyresampled() để thay đổi kích thước, sau đó gửi kết quả .jpg tới trình duyệt, nó được gọi là hành động điều khiển chuẩn.

Dường như hoạt động trong mọi trường hợp ngoại trừ khi ảnh gốc được người dùng lưu từ facebook (tức là nhấp chuột phải vào trình xem ảnh facebook và tải xuống máy tính để bàn rồi tải lên trang web của khách hàng). Tôi đã thử nghiệm này một số lần bản thân mình và có thể tái tạo nó. Tôi cũng có thể tải lên cùng một hình ảnh khi được lưu lại qua photoshop mà không gặp sự cố.

Tôi nghi ngờ hiển thị hình ảnh facebook thêm một số loại siêu dữ liệu bổ sung bên trong tệp khiến hệ thống của tôi bị hỏng.

Có giải pháp cho việc này không?

Mã cho mô-đun hình ảnh PHP là như sau:

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, 0, 0, $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, 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, //Destination Image 
      $inputImage, //Original Image 
      $left, $top, //Destination top left Coord 
      0, 0, //Source top left coord 
      $calculatedWidth, $calculatedHeight, //Final location Bottom Right Coord 
      $inputWidth, $inputHeight //Source bottom right coord. 
     ); 
    } 



    imagejpeg($finalImage, null, 100); 
    imagedestroy($inputImage); 
    imagedestroy($finalImage); 

} 

tôi nghi ngờ rằng vấn đề thực sự có thể nằm với việc thực hiện _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; 
      } 
    } 
} 

Bạn có thể thấy một ví dụ về vấn đề này tại http://www.angelaryan.com/gallery/Image/22 đó sẽ hiển thị một hình vuông màu xanh, chứ không phải là hình ảnh được lưu trữ trong cơ sở dữ liệu.

+0

Bạn có thể cung cấp hình ảnh mẫu từ Facebook không thành công? – DCoder

+0

Chắc chắn! bạn muốn mẫu được cung cấp như thế nào? –

+0

Bạn có thể đăng liên kết tới hình ảnh gốc hoặc tải lên một số trang chia sẻ tệp/FTP (không phải là dịch vụ chia sẻ hình ảnh chuyên biệt, vì có khả năng sẽ nén lại hình ảnh). – DCoder

Trả lời

3

Hãy thử tự động "lại tiết kiệm" hình ảnh sau khi upload với

imagejpeg(imagecreatefromjpeg($filename),$filename,9); 

này nên tạo lại bất kỳ tiêu đề bị thay đổi hoặc không được công nhận từ hình ảnh Facebook ban đầu.

0

Tôi nghĩ rằng bạn nên sử dụng getimagesizefromstring chức năng thay vì phân tích các dữ liệu thô tự hỏi:

list($width, $height, $type) = getimagesizefromstring($data); 

Resaving hình ảnh sẽ chỉ làm suy giảm chất lượng hình ảnh.

Các vấn đề liên quan