Статьи

Обработка изображений с помощью PHP — библиотеки GD

Библиотеки GD являются основным модулем PHP, используемым для работы с изображениями, и доступны в Boutel.Com, Inc.

Если вам повезло, что вы размещены (или действительно владеете) сервером, работающим на GD2.0 или выше, у вас будет возможность использовать изображения в истинном цвете в формате jpeg (и в png, если версия 2.0.4+) и, следовательно, Вы действительно не выиграете, прочитав этот учебник. Те, кто использует GD2.0 +, должны выбрать использование ImageCreateTrueColor вместо ImageCreate и ImageCopyResampled вместо ImageCopyResized чтобы обеспечить использование максимальных уровней цвета. Если вы используете что-то под 2.0, читайте дальше!

Создание изображения

Функция ImageCreate(x_dimension,y_dimension) в GD ограничена палитрой из 256 цветов и поэтому редко выводит изображение с качеством, приемлемым для большинства веб-дизайнеров. К счастью, есть способ обойти это ограничение и максимизировать палитру до 16,7 миллионов цветов. Для этого вам понадобится графический редактор, способный сохранять JPEG-файлы с нулевым сжатием, сервер с поддержкой GD и несколько свободных минут, чтобы прочитать это руководство.

Быстрое объяснение концепции …

Если вы используете ImageCreateFromJPEG($image_pointer ); Ваша полезная палитра будет точно имитировать ту из картинок, на которую вы указываете. Итак, если мы ImageCreate(width,height) функцию ImageCreate(width,height) и сосредоточимся на попытке использовать ImageCreateFromJPEG , мы должны перейти к лучшей палитре. Те из вас, кто знаком с GD (или более быстрые мыслители среди вас), возможно, уже заметили, что создание из размещенного изображения не позволяет нам указать ширину и высоту для изображения, которое мы создали. Если размер нашего ресурса составляет 400 на 200 пикселей, и мы хотим создать миниатюру с максимальным размером 100 пикселей, то нам нужно базовое изображение размером 100 на 50 пикселей.

Это ограничивает нас двумя вариантами:

  1. Либо мы загружаем базовые изображения со всеми изменениями ширины-высоты, необходимыми нашему сценарию, и диктуем, какое из них использовать в рамках небольшой базовой математики, или
  2. Мы используем одно изображение, размер которого соответствует любому размеру, который нам понадобится, и который будет рисоваться только в обозначенной области этого размера, оставляя все края пустыми / цвет страницы.

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

Остальная часть этого урока будет посвящена второму варианту. Мы рассмотрим, как определить, к какой области созданного изображения нужно рисовать, и приведенные здесь советы и подсказки помогут вам быстро приступить к работе!

Основные правила миниатюр

1. Будьте добры к вашему серверу

Легко отобразить группу миниатюр, просто просматривая изображения в каталоге и проталкивая их через скрипт миниатюр. Поскольку это так просто, некоторые люди делают именно это при каждой загрузке страницы, которая, очевидно, немного жадна до ресурсов сервера. Гораздо лучшая альтернатива — сохранить фактическое эскизное изображение на сервере и просто отобразить его.

2. Защитите свои миниатюрные сценарии

Для универсальности вам понадобятся несколько переменных, которые управляют выводом миниатюры. По крайней мере, вам понадобится указатель изображения, возможно, переключатель, который позволит вам сохранить копию на сервере, если потребуется, и, возможно, параметр сжатия. Имея такие, вы захотите убедиться, что никто не сможет ввести URL, который переопределит ваши обычные настройки. Типичные варианты сессий или .htaccess подойдут.

Скрипты

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

Как мы уже обсуждали, мы хотим иметь несколько переменных, которые позволяют нам указывать образ нашего ресурса, контролировать, сохраняется ли копия на сервере, и контролировать степень сжатия вывода.

Но мы также можем использовать проверку сеанса для контроля запуска скрипта или нет. Возможно, наша административная панель может зарегистрировать сеанс с именем allow_thumbs , чтобы включить скрипт. Мы бы назвали этот скрипт, используя атрибут src <img> , так:

 <img src="thumb.php?basepath=foldername/  &img_ref=nicebig.jpg&create=yes&compress=65"> 

Поскольку мы будем каждый раз использовать одно и то же базовое изображение, мы также можем жестко запрограммировать размеры в тег вместе с alt= . Без сомнения, вы найдете свою собственную систему для создания тега вызова, основанную на текущей настройке администрации.

Еще одна вещь, которую стоит отметить при вызове через src <img> заключается в том, что любые ошибки синтаксического анализа, возникающие в скрипте, не будут отображаться на странице. Все, что произойдет, это то, что вы увидите на своей странице место, где не было изображения. Если вам нужно увидеть сообщения об ошибках в целях отладки, вам нужно временно снять защиту сеанса и получить доступ к сценарию напрямую через URL-вызов.

Следующий скрипт создаст миниатюру, используя пустое базовое изображение, а не функцию ImageCreate() . Объяснение конкретных синтаксисов приведено ниже.

 session_start();  if($HTTP_SESSION_VARS["allow_thumbs"] == "yes")  {  header ("Content-type: image/jpeg");   // define the small, square image that will be  // used as the thumbnail base   $palette_image = 'foldername/large_palette_base_image.jpg';   /****** You shouldn't need to edit below here ******/   // Set some defaults values for variables that have not  // been passed to the script through the url   if(!isset($HTTP_GET_VARS['create']))  {$HTTP_GET_VARS['create'] = 'no';}  if(!isset($HTTP_GET_VARS['basepath']))  {$HTTP_GET_VARS['basepath'] = '';}  if(!isset($HTTP_GET_VARS['compress']))  {$HTTP_GET_VARS['compress'] = 100;}   // establish where on the thumbnail we can draw to   $thumbsize = getImageSize($palette_image);  $maxdim = $thumbsize[0];  $draw_from = $HTTP_GET_VARS['basepath'].$HTTP_GET_VARS['img_ref'];  $dim = GetImageSize($draw_from);  if($dim[0]>$dim[1])  {  $to_w = $maxdim;  $to_h = round($dim[1]*($maxdim/$dim[0]));  $to_x = 0;  $to_y = round($maxdim-$to_h)/2;  }  else  {  $to_h = $maxdim;  $to_w = round($dim[0]*($maxdim/$dim[1]));  $to_y = 0;  $to_x = round($maxdim-$to_w)/2;  }   // create some base images to start designing from  // and make initial basic thumbnail   if($dim[2]==1) {$from = ImageCreateFromGIF($draw_from);}  elseif($dim[2]==2) {$from = ImageCreateFromJPEG($draw_from);}  elseif($dim[2]==3) {$from = ImageCreateFromPNG($draw_from);}  $thumb = ImageCreateFromJPEG($palette_image);  // $set_bg_colour = ImageColorAllocate($thumb,255,0,0);  // $fill_bg_colour = ImageFill($thumb,0,0,$set_bg_colour);  ImageCopyResized($thumb, $from, $to_x, $to_y, 0,  0, $to_w, $to_h, $dim[0], $dim[1]);   /******* Image Manipulation Scripting *******/   // extra image manipulation can go here   /***** End Image Manipulation Scripting *****/   // output the created thumnbnail onto the calling page  // and, if $create has been set to 'yes', also create  // a copy of the thumbnail on the server   ImageJPEG($thumb,'',$HTTP_GET_VARS['compress']);  if($HTTP_GET_VARS['create'] == "yes")  {  ImageJPEG($thumb,$HTTP_GET_VARS['basepath'].substr  ($HTTP_GET_VARS['img_ref'],0,  strpos($HTTP_GET_VARS['img_ref'],'.')).'_thumb.jpg',  $HTTP_GET_VARS['compress']);  }   // destroy all the temporary images used by the  //server while executing this  scriptlet (tidying up)   ImageDestroy($from);  ImageDestroy($thumb);  } 

Приведенный выше скрипт возьмет изображение ресурса (на которое ссылается img_ref = в вызывающем URL-адресе) и уменьшит его до миниатюры, которая вписывается в центр изображения палитры (пустое изображение, используемое для расширения палитры). Индексы палитры на результирующем миниатюре будут увеличены до максимального размера, соответствующего размеру изображения палитры. Вы можете скопировать приведенный выше скрипт и ссылаться на него в следующих пояснениях.

Синтаксис Пояснения

Давайте теперь пройдемся по сценарию и исследуем, что происходит в каждой точке.

  • сессия
  • - просто там для безопасности. Вы могли бы сделать session_start(); $allow_thumbs = "yes"; session_register("allow_thumbs"); session_start(); $allow_thumbs = "yes"; session_register("allow_thumbs"); на вашей странице администратора, чтобы активировать миниатюру.

    Кроме того, вы можете удалить части сеанса и поместить сценарий миниатюр в папку с защитным файлом .htaccess. В любом случае, просто убедитесь, что люди не могут получить доступ к сценарию, введя URL-адрес.

  • Заголовок ()
  • - для вывода на страницу или в файл необходимо отправить тип заголовка. Мы выбрали jpeg из-за его способности к сжатию.
  • $ palette_image
  • - путь (абсолютный от корня или относительно этого сценария) и имя квадратного пустого изображения, которое должно использоваться в качестве основы для миниатюр. Я подчеркнул «квадрат», потому что вы должны использовать квадратное изображение с приведенным выше сценарием. Чтобы создать красивое истинное цветное изображение, просто:

  • откройте свою графическую программу,

  • сделать новое квадратное (я уже говорил, что оно должно быть квадратным) изображение,
  • увеличить глубину цвета до максимальной (если это еще не сделано), и

  • сохранить как .jpg.

    Вы также можете заполнить его тем же цветом, что и фон вашей страницы перед сохранением. Наконец, загрузите его и измените значение $palette_image для ссылки на этот новый файл.

  • значения по умолчанию - чтобы избежать необходимости передавать каждую пару переменная = значение через URL-вызов, мы просто устанавливаем некоторые значения по умолчанию для использования, если переменная не установлена. Например, если бы мы вызывали изображение с img src="thumb.php?img_ref=blat.png" , скрипт автоматически установил бы create=no, basepath='' and compress=100.
  • установить область рисования - используя GetImageSize() , мы находим высоту и ширину как нашего изображения ресурса, так и базы миниатюр. Мы проверяем, что больше на изображении ресурса (будь то портрет или пейзаж) и уменьшаем его, чтобы имитировать пространство, доступное на базе миниатюр. Затем можно использовать некоторую достаточно простую математику для определения другого измерения и верхнего левого пикселя нашей области рисования. У нас есть...
  • $ to_h
  • - высота области рисования
  • $ to_w
  • - ширина области рисования
  • $ to_x
  • - горизонтальное положение первого пикселя, отсчитываемое слева
  • $ to_y
  • - вертикальная позиция первого пикселя, отсчитываемая сверху

  • создать несколько изображений - чтобы GD мог выполнять любые манипуляции с изображениями, ему необходимо создать копию назначенного изображения и работать с этим. Нам нужно создать два изображения, базу миниатюр (которую мы назвали $thumb ) и копию изображения ресурса (которое мы назвали $from ). Наше раннее использование GetImageSize для образа ресурса также дало индекс, который содержит GetImageSize . Быстрое тестирование ценности покажет, что мы можем создать нашу копию этого изображения - будь то .gif, .png или .jpg - что означает, что наш скрипт стал более универсальным.

  • // $set_bg_colour - если вы не заполнили базовое изображение миниатюры тем же цветом, что и фон страницы, удалите комментарий этой строки и строки $ fill_bg_colour. Вы должны вставить значения rgb в ImageColorAllocate($thumb, red, green, blue) чтобы имитировать цвет вашей страницы. Вы можете даже передать их как переменные в вызывающем URL.

  • ImageCopyResized - используя все математически выведенные значения, мы используем эту функцию, чтобы взять всю область нашего изображения ресурса, уменьшить его и скопировать в строго определенную область нашей базы миниатюр.

  • /* image manipulation scripting */ - если бы мы хотели выполнить какие-либо дальнейшие манипуляции с нашим эскизом, мы бы сделали это в этой области. Далее в этом уроке есть пара фрагментов кода, которые вы можете подключить здесь.

  • ImageJPEG - это вызов, который выводит изображение в браузер.

  • if (create = "yes") - чтобы сохранить копию созданного нами эскиза на сервере, нам нужно использовать средний параметр функции ImageJPEG . Мы проверяем, была ли наша переменная create явно установлена ​​на «да», и, если так, мы разрываем имя образа ресурса, чтобы удалить расширение, и создаем файл на основе [этого имени изображения] _thumb.jpg.

    Обратите внимание, что вам понадобится каталог, в который вы сохраняете свои миниатюры, чтобы он был изменен на довольно высокие разрешения. Возможно, вы также захотите поместить миниатюры в отдельный каталог, и в этом случае вы захотите изменить путь, например. $HTTP_GET_VARS['basepath']. 'thumbnail_folder/' .substr($.... $HTTP_GET_VARS['basepath']. 'thumbnail_folder/' .substr($....

  • ImageDestroy - поскольку GD пришлось создавать изображения для работы, мы заканчиваем все сценарии манипуляции удалением этих временных изображений с сервера.

    Я протестировал этот скрипт, используя GD1.6.2 и GD1.8.4, которые оба выполнялись превосходно - безусловно, улучшение 256 цветов, разрешенных при использовании ImageCreate() .

    Теперь у нас есть основы, давайте посмотрим, как мы можем использовать дополнительные функции манипулирования изображениями ...

    Дальнейшие манипуляции

    В предыдущем сценарии была область, закомментированная как /* image manipulation scripting */ , которая была пустой. Если бы мы хотели попробовать несколько странных и замечательных эффектов на наших миниатюрах, мы могли бы добавить сюда код, объединяющий все переменные, которые мы определили или вывели ранее.

    Примером идеи может быть добавление затененного скоса к миниатюре, возможно со светлым оттенком сверху и слева и темным цветом справа и снизу. Чтобы дать вам представление о применяемых методах, я возьму идею затененного скоса и медленно пройдусь по ней.

    Затененный скос

    Полезная функция в GD - ImageCopyMerge, как она позволяет нам объединить часть одного изображения с миниатюрой. Это особенно полезно, потому что мы также можем определить непрозрачность для объединенной части (что для нас с вами означает затенение). Если мы используем короткий цикл for для подсчета расстояния до каждого края эскиза, мы также можем использовать это инкрементное число для определения непрозрачности, с которой мы будем рисовать наши темные и светлые линии.

     // create a dark image and a light image   $dark_shadey = ImageCreate($maxdim,$maxdim);  $nadir = ImageColorAllocate($dark_shadey,0,0,0);  $light_shadey = ImageCreate($maxdim,$maxdim);  $nadir = ImageColorAllocate($light_shadey,255,255,255);   // decide how wide we want our edge shading   $edge_width = 10;  for($edge_pixel = 0; $edge_pixel < $edge_width; $edge_pixel++)  {   // work out the opacity relative to how far from the edge we are   $opacity =  100 - (($edge_pixel+1) * (100 / $edge_width));   // merge a bit of the light image along the top and left side  // merge a bit of the dark image along the base and right side   ImageCopyMerge($thumb,$light_shadey,$to_x+($edge_pixel-1),  $to_y+($edge_pixel-1),0,0,1,$to_h-(2*$edge_pixel),$opacity);  ImageCopyMerge($thumb,$light_shadey,$to_x+($edge_pixel-1),  $to_y+($edge_pixel-1),0,0,$to_w-(2*$edge_pixel),1,$opacity);  ImageCopyMerge($thumb,$dark_shadey,$to_x+($to_w-($edge_pixel+1)),  $to_y+$edge_pixel,0,0,1,$to_h-(2*$edge_pixel),$opacity-20);  ImageCopyMerge($thumb,$dark_shadey,$to_x+$edge_pixel,$to_y+  ($to_h-($edge_pixel+1)),0,0,$to_w-(2*$edge_pixel),1,$opacity-20);  }   // destroy the two new images that we used   ImageDestroy($dark_shadey);  ImageDestroy($light_shadey); 

    Вы могли заметить, что я использовал несколько странных синтаксисов, таких как уменьшение непрозрачности темного изображения на 20 в вызовах ImageCopyMerge . Это просто потому, что результирующее изображение выглядит лучше, если темнота не так темна, как свет. Если вы решите кодировать свои собственные манипуляции, вам (более чем вероятно) придется добавить несколько обходных синтаксисов, подобных этому, в ваши собственные сценарии.

    Просто для продолжения, вот еще пара манипуляций, которые можно вырезать и вставить в область /* image manipulation scripting */ основного учебного сценария.

    Паучья паутина

    Этот небольшой плагин скриптлетов создает веб-эффект паука, который рисуется поверх миниатюры в цвете, определенном как $zenith . Этот сценарий просто рисует несколько линий из нижнего левого угла под разными углами, а затем рисует эллиптические дуги с центром в том же углу.

     $zenith = ImageColorAllocate($thumb,255,255,255);  for($draw = 0;$draw<$to_h;$draw+=12)  {  ImageLine($thumb,$to_x,($to_h+$to_y),($to_w+$to_x),  (($to_h-$draw)+$to_y),$zenith);  }  for($draw = 0;$draw<$to_w;$draw+=12)  {  ImageLine($thumb,$to_x,($to_h+$to_y),($draw+$to_x),  $to_y,$zenith);  }  for($draw = 1;$draw<14;$draw++)  {  ImageArc($thumb,$to_x,($to_h+$to_y),$draw*($to_w/4),$draw*  ($to_h/4),270,0,$zenith);  } 

    Пончик

    Этот более крупный скриптлет-плагин создает эллиптическую затененную миниатюру пончика. Цвет фона и тени определяется $zenith . Эта манипуляция работает, повторяя миниатюру по одному пикселю за раз, и решая, какую именно непрозрачность применить при объединении маленькой точки в этом месте.

     $dot = ImageCreate(1,1);  $zenith = ImageColorAllocate($dot,255,255,255);   for($ypos=0;$ypos<$to_h;$ypos++)  {  for($xpos=0;$xpos<$to_w;$xpos++)  {  $xdist = abs(($to_w/2)-$xpos);  if($xdist==0) {$xdist = 0.01;}  $ydist = abs(($to_h/2)-$ypos);  $dist = sqrt(pow($xdist,2)+pow($ydist,2));  $angl = atan($ydist/$xdist);  $el_dist =  sqrt(pow(abs(cos($angl)*$to_w/2),2)+pow(abs(sin($angl)*$to_h/2),2));  if($dist>$el_dist || $dist<$el_dist/6)  {  ImageCopyMerge($thumb,$dot,$xpos+$to_x,$ypos+$to_y,0,0,1,1,100);  }  else {  $dnut_dist = ($el_dist/12)*5;  $offset_dist = abs((($el_dist/12)*7)-$dist);  $uppy = sin(acos($offset_dist/$dnut_dist))*$dnut_dist;  $opac = 100-((100/$dnut_dist)*$uppy);  ImageCopyMerge($thumb,$dot,$xpos+$to_x,$ypos+$to_y,0,0,1,1,$opac);  }  }  }  ImageDestroy($dot); 

    Я надеюсь, что этот учебник и дополнительные маленькие скриптлеты научили вас, насколько универсальными могут быть библиотеки GD. Возможно, вы даже поймали ошибку манипуляции с изображениями и хотите начать кодировать свои собственные преобразования! Удачи.