2008-08-22 22 views
9

Tôi muốn cho phép người dùng tải lên hình ảnh loại hình đại diện ở nhiều định dạng khác nhau (GIF, JPEG và PNG ít nhất), nhưng để lưu chúng dưới dạng cơ sở dữ liệu PNG BLOBs. Nếu hình ảnh quá lớn, theo chiều kim đồng hồ, tôi muốn đổi kích thước hình ảnh trước khi chèn DB.Làm cách nào để thay đổi kích thước và chuyển đổi hình ảnh đã tải lên thành PNG bằng GD?

Cách tốt nhất để sử dụng GD để thực hiện thay đổi kích thước và PNG là gì?

Chỉnh sửa: Đáng buồn thay, chỉ GD khả dụng trên máy chủ tôi cần sử dụng, không ImageMagick.

+0

Không phân phát hoặc lưu trữ hình ảnh từ hoặc đến DB. – dlamblin

Trả lời

23
<?php            
/* 
Resizes an image and converts it to PNG returning the PNG data as a string 
*/ 
function imageToPng($srcFile, $maxSize = 100) { 
    list($width_orig, $height_orig, $type) = getimagesize($srcFile);   

    // Get the aspect ratio 
    $ratio_orig = $width_orig/$height_orig; 

    $width = $maxSize; 
    $height = $maxSize; 

    // resize to height (orig is portrait) 
    if ($ratio_orig < 1) { 
     $width = $height * $ratio_orig; 
    } 
    // resize to width (orig is landscape) 
    else { 
     $height = $width/$ratio_orig; 
    } 

    // Temporarily increase the memory limit to allow for larger images 
    ini_set('memory_limit', '32M'); 

    switch ($type) 
    { 
     case IMAGETYPE_GIF: 
      $image = imagecreatefromgif($srcFile); 
      break; 
     case IMAGETYPE_JPEG: 
      $image = imagecreatefromjpeg($srcFile); 
      break; 
     case IMAGETYPE_PNG: 
      $image = imagecreatefrompng($srcFile); 
      break; 
     default: 
      throw new Exception('Unrecognized image type ' . $type); 
    } 

    // create a new blank image 
    $newImage = imagecreatetruecolor($width, $height); 

    // Copy the old image to the new image 
    imagecopyresampled($newImage, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig); 

    // Output to a temp file 
    $destFile = tempnam(); 
    imagepng($newImage, $destFile); 

    // Free memory       
    imagedestroy($newImage); 

    if (is_file($destFile)) { 
     $f = fopen($destFile, 'rb'); 
     $data = fread($f);  
     fclose($f); 

     // Remove the tempfile 
     unlink($destFile);  
     return $data; 
    } 

    throw new Exception('Image conversion failed.'); 
} 
+0

Cảm ơn giải pháp này! :) Nó thậm chí hoạt động với một phần bức ảnh trong suốt (đó là vấn đề ban đầu của tôi)! – bastiandoeen

0

This article có vẻ như nó phù hợp với những gì bạn muốn. Bạn sẽ cần phải thay đổi hàm imagejpeg() thành imagepng() và lưu nó vào một chuỗi thay vì xuất nó ra trang, nhưng khác với nó nên dễ dàng sao chép/dán vào mã hiện có của bạn.

0

GD có bắt buộc hoàn toàn không? ImageMagick là nhanh hơn, tạo ra hình ảnh tốt hơn, có thể cấu hình nhiều hơn và cuối cùng là (IMO) dễ dàng hơn để mã hóa.

+0

Âm thanh nhưng là một thương mại đơn giản. Bất kỳ bằng chứng nào? – Green

+0

Chắc chắn. Để tạo hình thu nhỏ được cắt: '$ image = new Imagick ($ image_path); $ image-> cropThumbnailImage (100,100); 'Hãy thử làm điều đó trong GD trong hai dòng mã. ImageMagick là một bộ công cụ được thiết kế đặc biệt để thao tác hình ảnh, do đó, nó thường sẽ tốt hơn so với một phần ngẫu nhiên của PHP. – ceejayoz

0

Tôi nghĩ this page là điểm khởi đầu tốt. Nó sử dụng imagecreatefrom (jpeg/gif/png) và thay đổi kích thước và chuyển đổi hình ảnh và sau đó xuất ra trình duyệt. Thay vì xuất ra trình duyệt, bạn có thể xuất ra BLOB trong DB mà không cần nhiều lần viết mã.

3

Nếu bạn muốn sử dụng gdlib, hãy sử dụng gdlib 2 trở lên. Nó có một chức năng gọi là imagecopyresampled(), sẽ nội suy các pixel trong khi thay đổi kích thước và trông đẹp hơn nhiều.

Ngoài ra, tôi đã luôn luôn nghe ghi nhận khắp nơi trên net mà lưu trữ hình ảnh trong cơ sở dữ liệu là hình thức xấu:

  • Đó là chậm hơn để truy cập hơn so với đĩa
  • Máy chủ của bạn sẽ cần phải chạy một kịch bản để đến được với các hình ảnh thay vì chỉ đơn giản là phục vụ một file
  • kịch bản của bạn bây giờ là trách nhiệm rất nhiều thứ máy chủ web được sử dụng để xử lý :
    • Se tting tiêu đề Loại Nội dung phù hợp
    • Đặt tiêu đề bộ nhớ đệm/thời gian chờ/E-tag thích hợp để khách hàng có thể lưu hình ảnh đúng cách. Nếu không làm điều này đúng cách, tập lệnh phục vụ hình ảnh sẽ được nhấn vào mọi yêu cầu, tăng tải trên máy chủ nhiều hơn.

Ưu điểm duy nhất tôi có thể thấy là bạn không cần phải giữ cho cơ sở dữ liệu và hình ảnh của bạn file đồng bộ. Tôi vẫn sẽ khuyên bạn nên chống lại nó mặc dù.

+0

Nó chắc chắn hút để phục vụ hình ảnh ra khỏi một DB so với offloading chúng vào máy chủ tĩnh nhẹ wieght của họ trên một miền tĩnh hoặc một cdn. – dlamblin

6

bước của bạn quá trình sẽ giống như sau:

  1. Verify các filetype
  2. tải hình ảnh nếu nó là một filetype được hỗ trợ vào GD sử dụng imagecreatefrom*
  3. Thay đổi kích thước sử dụng imagecopyresize hoặc imagecopyresampled
  4. Save the hình ảnh sử dụng imagepng($handle, 'filename.png', $quality, $filters)

ImageMagick nhanh hơn, tạo ra hình ảnh tốt hơn, có thể cấu hình nhiều hơn và cuối cùng là (IMO) dễ dàng hơn để mã hóa.

@ceejayoz Chỉ cần chờ cho GD mới - đó là OOP như MySQLi và nó thực sự không xấu :)

3

Bạn có chắc chắn bạn không có ImageMagick trên máy chủ?

Tôi khách bạn sử dụng PHP (câu hỏi được gắn thẻ bằng PHP). Công ty lưu trữ mà tôi sử dụng không có phần mở rộng ImageMagick được bật theo phpinfo().

Nhưng khi tôi hỏi họ về họ nói đây là danh sách các chương trình ImageMagick có sẵn từ mã PHP. Vì vậy, đơn giản - không có giao diện IM trong PHP, nhưng tôi có thể gọi các chương trình IM trực tiếp từ PHP.

Tôi hy vọng bạn có cùng tùy chọn.

Và tôi mạnh mẽ đồng ý - lưu trữ hình ảnh trong cơ sở dữ liệu không phải là ý tưởng hay.

3

Something như thế này, có lẽ:


<?php 
    //Input file 
    $file = "myImage.png"; 
    $img = ImageCreateFromPNG($file); 

    //Dimensions 
    $width = imagesx($img); 
    $height = imagesy($img); 
    $max_width = 300; 
    $max_height = 300; 
    $percentage = 1; 

    //Image scaling calculations 
    if ($width > $max_width) { 
     $percentage = ($height/($width/$max_width)) > $max_height ? 
      $height/$max_height : 
      $width/$max_width; 
    } 
    elseif ($height > $max_height) { 
     $percentage = ($width/($height/$max_height)) > $max_width ? 
      $width/$max_width : 
      $height/$max_height; 
    } 
    $new_width = $width/$percentage; 
    $new_height = $height/$percentage; 

    //scaled image 
    $out = imagecreatetruecolor($new_width, $new_height); 
    imagecopyresampled($out, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height); 

    //output image 
    imagepng($out); 
?> 

tôi đã không kiểm tra mã để có thể có một số lỗi cú pháp, tuy nhiên nó sẽ cho bạn một trình bày hợp lý về cách nó có thể được thực hiện. Ngoài ra, tôi giả định một tệp PNG. Bạn có thể muốn có một số loại tuyên bố chuyển đổi để xác định loại tệp.