2008-08-22 11 views
9

Я хочу разрешить пользователям загружать аватарные изображения в различных форматах (GIF, JPEG и PNG не менее), но для их сохранения в качестве PNG database BLOB. Если изображения негабаритных, по-пиксели, я хочу изменить их размер перед вставкой DB.Как изменить размер и преобразовать загруженное изображение в PNG с помощью GD?

Каков наилучший способ использования GD для изменения размера и преобразования PNG?

Редактировать: К сожалению, только GD доступен на сервере, который мне нужно использовать, нет ImageMagick.

+0

Не обслуживайте и не храните изображения с БД или из него. – dlamblin

ответ

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

Спасибо за это решение! :) Это даже работает с частично прозрачными фотографиями (это была моя оригинальная проблема)! – bastiandoeen

0

This article похоже, что он поместит то, что вы хотите. Вам нужно будет изменить функцию сохранения imagejpeg() на imagepng() и сохранить файл в строке, а не выводить его на страницу, но, кроме того, это будет легко скопировать/вставить в существующий код.

0

Обязательно ли GD? ImageMagick быстрее, генерирует лучшие изображения, более настраивается и, наконец, (IMO) намного проще кодировать.

+0

Звучит, но простая реклама. Какие-нибудь доказательства? – Green

+0

Несомненно. Чтобы сделать обрезанное миниатюру: $ image = new Imagick ($ image_path); $ image-> cropThumbnailImage (100,100); 'Попробуйте сделать это в GD в двух строках кода. ImageMagick - это инструментарий, разработанный специально для управления изображениями, поэтому он, как правило, будет лучше, чем случайная брошенная часть PHP. – ceejayoz

0

Я думаю, this page является хорошей отправной точкой. Он использует imagecreatefrom (jpeg/gif/png) и изменяет размер и преобразует изображение, а затем выводит его в браузер. Вместо вывода браузера вы можете выводить на BLOB в БД без много минут перезаписи кода.

3

Если вы хотите использовать gdlib, используйте gdlib 2 или выше. Он имеет функцию imagecopyresampled(), которая будет интерполировать пиксели при изменении размера и выглядеть намного лучше.

Кроме того, я всегда слышал, отметил вокруг сети, что хранение изображений в базе данных является плохой формой:

  • Это медленнее доступ, чем диск
  • Вашего сервер должен выполнить скрипт для получить к изображению вместо просто служит файл
  • Ваш скрипт теперь отвечает за многие вещи веб-сервер, используемый для обработки :
    • Se tting правильного заголовка Content-Type
    • Настройка правильных заголовков кэширования/таймаута/E-тегов, чтобы клиенты могли правильно кэшировать изображение. Если вы не сделаете это правильно, сценарий обслуживания изображений будет удален по каждому запросу, что еще больше увеличит нагрузку на сервер.

Единственное преимущество я вижу в том, что вам не нужно, чтобы сохранить ваши файлы базы данных и изображений синхронизируется. Тем не менее, я бы порекомендовал его.

+0

Это определенно отстой, чтобы обслуживать изображения из БД по сравнению с их разгрузкой их собственным статическим сервером света в статическом домене или cdn. – dlamblin

6

Ваши шаги процесса должны выглядеть следующим образом:

  1. Verifyfiletype
  2. Загрузите изображение, если это поддерживается Filetype в GD с использованием imagecreatefrom*
  3. Изменение размера с помощью imagecopyresize или imagecopyresampled
  4. Сохраните изображение с использованием imagepng($handle, 'filename.png', $quality, $filters)

ImageMagick работает быстрее, генерирует лучшие изображения, более настраивается и, наконец, (IMO) намного проще кодировать.

@ceejayoz Просто ждать нового GD - это ООП как MySQLi и это на самом деле не плохо :)

3

Вы уверены, что у вас нет ImageMagick на сервере?

Я гость вы используете PHP (вопрос помечен PHP). Хостинговая компания, которой я пользуюсь, не поддерживает расширение ImageMagick в соответствии с phpinfo().

Но когда я спросил их, они сказали вот список программ ImageMagick, доступных из кода PHP. Так просто - в PHP нет интерфейса IM, но я могу вызывать IM-программы непосредственно с PHP.

Надеюсь, у вас есть тот же вариант.

И я сильно согласен - хранение изображений в базе данных - это не очень хорошая идея.

3

Что-то вроде этого, возможно:


<?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); 
?> 

Я не проверял код, так что могут быть некоторые ошибки синтаксиса, однако это должно дать вам справедливое представление о том, как это может быть сделано. Кроме того, я принял PNG-файл. Для определения типа файла может потребоваться какой-то оператор switch.

0

phpThumb - это абстракция высокого уровня, на которую стоит обратить внимание.