Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

   Интернет технологии -> PHP -> Играем с изображением в PHP


Играем с изображением в PHP

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

Например, мы можем сделать негатив изображения. Для этого берем каждый пиксель в изображении и заменяем его противоположным цветом.

Хорошо, но как это работает? Очень просто. Я беру картинку PNG, прохожу по каждому пикселю этого изображения и передаю его функции, которая принимает пиксель в качестве параметра. Функция возвращает мне новый пиксель. Я складываю все новые пиксели и получаю новое изображение.

Класс для работы с пикселом

Для начала нам понадобится класс для работы с пикселом. Он очень прост – содержит в себе три значения: красного, зеленого и синего.

<?php
class Pixel {
    function
Pixel($r, $g, $b)
    {
        
$this->r = ($r > 255) ? 255 : (($r < 0) ? 0 : (int)($r));
        
$this->g = ($g > 255) ? 255 : (($g < 0) ? 0 : (int)($g));
        
$this->b = ($b > 255) ? 255 : (($b < 0) ? 0 : (int)($b));
    }
}
?>

Этот класс имеет только одну функцию – конструктор, которая сохраняет RGB значения пикселя.

Чтобы создать красный пиксел, вы просто делаете:

<?php
$red
= new Pixel(255, 0, 0);
?>

Класс манипуляций с пикселами: главный метод

Далее мы создаем класс, который проделывает фактические действия с изображением. Назовем его Image_PixelOperations(). Я не стал писать удобного интерфейса для обработки различных форматов картинок, я думаю, что вы можете развить его самостоятельно. Все, что мне было нужно – это более простой метод для открытия PNG файлов, который бы проходил по каждому пикселу файла, вызывает функцию, получает новый пиксел и присваивает его новому изображению. Далее приведу текст метода:

<?php
class Image_PixelOperations {
        
    function
pixelOperation(
            
$input_image,
            
$output_image,
            
$operation_callback,
            
$factor = false
            
)
    {
        
        
$image = imagecreatefrompng($input_image);
        
$x_dimension = imagesx($image);
        
$y_dimension = imagesy($image);
        
$new_image = imagecreatetruecolor($x_dimension, $y_dimension);
        
        if (
$operation_callback == 'contrast') {
            
$average_luminance = $this->getAverageLuminance($image);
        } else {
            
$average_luminance = false;
        }
        
        for (
$x = 0; $x < $x_dimension; $x++) {
            for (
$y = 0; $y < $y_dimension; $y++) {
        
                
$rgb = imagecolorat($image, $x, $y);
                
$r = ($rgb >> 16) & 0xFF;
                
$g = ($rgb >> 8) & 0xFF;
                
$b = $rgb & 0xFF;
        
                
$pixel = new Pixel($r, $g, $b);
                
$pixel = call_user_func(
                    
$operation_callback,
                    
$pixel,
                    
$factor,
                    
$average_luminance
                
);
        
                
$color = imagecolorallocate(
                    
$image,
                    
$pixel->r,
                    
$pixel->g,
                    
$pixel->b
                
);
                
imagesetpixel($new_image, $x, $y, $color);
            }
        
        }
        
        
imagepng($new_image, $output_image);
    }
}
        
?>

Метод принимает путь до файла. Никаких проверок не производит, предполагая, что это правильный PNG файл. Второй параметр – это имя нового файла изображения. Третий – функция, которая будет вызываться для каждого пикселя. И последний параметр – это любой дополнительный параметр, который мы хотели бы передать в вызываемую для пиксела функцию.

Добавляем шумов

И так, пришло время, чтобы написать первую функцию обработки пиксела: addNoise(). Добавление шума к изображению означает добавление случайного значения к каждому каналу пикселя (если у вас возник вопрос, что такое канал, то я отвечу – уровень красного цвета в пикселе = канал, тоже самое с зеленым и синим). Далее привожу функцию:

<?php
    
function addNoise($pixel, $factor)
    {
        
$random = mt_rand(-$factor, $factor);
        return new
Pixel(
                    
$pixel->r + $random,
                    
$pixel->g + $random,
                    
$pixel->b + $random
                
);
    }
?>

Что представляет из себя функция? Она получает случайное число в указанном пользователем диапазоне ($factor). И добавляет его к значению каналов пиксела. Пользователь указывает диапазон уровня шума: 0 – нет шума, 255 – очень много шума.

Давайте проверять! Создаем простую HTML форму:

<form method="get">
    <input name="image" />
    <input type="submit" />
</form>

Она принимает параметр – названия файла с изображением. После получения этого параметра я создаю новый объект класса для работы с пикселами:

<?php
if (!empty($_GET['image'])) {
        
    
$po =& new Image_PixelOperations();
        
}
?>

Далее я показываю оригинальное изображение, а затем результат обработки.

<?php
    
echo 'Оригинал: <br /><img src="'. $_GET['image'] .'" />';
    echo
'<hr />';
        
    
// Шумы
    
$noise = 100;
    
$po->pixelOperation($_GET['image'], 'result_noise.png', array($po, 'addNoise'), $noise);
    echo
'<br />Добаляем шумы (factor '. $noise .'): <br /><img src="result_noise.png" />';
    echo
'<hr />';
        
?>

Результат:

Рис. 1

Вот еще примеры. Первое изображение получено при помощи фактора 20, а второе – 500:

Рис. 2 Рис. 3

Управление яркостью

Давайте теперь попробуем поиграть с яркостью изображения. Нижеприведенная функция добавляет целое число (одно и тоже) к каждому каналу пиксела. Если мы вызываем функцию с положительным значением – яркость увеличивается, если с отрицательным – уменьшается.

<?php
function adjustBrightness($pixel, $factor)
{
    return new
Pixel(
    
$pixel->r + $factor,
    
$pixel->g + $factor,
    
$pixel->b + $factor
    
);
}
?>

Чтобы протестировать эту функцию выполните следующий код:

<?php
$brightness
= 50;
$po->pixelOperation($_GET['image'], 'result_bright.png', array($po, 'adjustBrightness'), $brightness);
echo
'<br />Ярче: <br /><img src="result_bright.png" />';
$brightness = -50;
$po->pixelOperation($_GET['image'], 'result_dark.png', array($po, 'adjustBrightness'), $brightness);
echo
'<br />Темнее: <br /><img src="result_dark.png" />';
echo
'<hr />';
?>

Смотрим на результат:

Рис. 4 Рис. 5

Меняем местами цвета

Давайте теперь займемся сменой цветов. Это означает, что мы можем взять, скажем, количество красных цветов и заменить их, например, на количество синих цветов. Возможные варианты:

  • RGB to RBG
  • RGB to BGR
  • RGB to BRG
  • RGB to GBR
  • RGB to GRB

Давайте посмотрим, как выглядит функция:

<?php
function swapColors($pixel, $factor)
{     
    switch (
$factor) {         
        case
'rbg':         
        return new
Pixel(         
        
$pixel->r,         
        
$pixel->b,         
        
$pixel->g         
        
);         
        break;         
        case
'bgr':         
        return new
Pixel(         
        
$pixel->b,         
        
$pixel->g,         
        
$pixel->r         
        
);         
        break;         
        case
'brg':         
        return new
Pixel(         
        
$pixel->b,         
        
$pixel->r,         
        
$pixel->g         
        
);         
        break;         
        case
'gbr':         
        return new
Pixel(         
        
$pixel->g,         
        
$pixel->b,         
        
$pixel->r         
        
);         
        break;         
        case
'grb':         
        return new
Pixel(         
        
$pixel->g,         
        
$pixel->r,         
        
$pixel->b         
        
);         
        break;         
        default:         
        return
$pixel;         
    }         
}
?>

Тестируем:

RGB -> RBG
Рис. 6
RGB -> BGR
Рис. 7
RGB -> BRG
Рис. 8
RGB -> GBR
Рис. 9
RGB -> GRB
Рис. 10

Удаление или насыщение цветов

Далее рассматриваем еще 2 функции. Первая – устанавливает значение цвета в 0 (например, нет красного). Вторая – наоборот увеличивает колличество цвета до максимального значения, или сразу 2 канала. Таким образом, мы имеем 6 вариантов значений для каждого метода.

  • Удаление (или насыщение) красный
  • Удаление (или насыщение) зеленый
  • Удаление (или насыщение) синий
  • Удаление (или насыщение) красный и зеленый в то же самое время
  • Удаление (или насыщение) красный и синий
  • Удаление (или насыщение) зеленый и синий

Код:

<?php
function removeColor($pixel, $factor)
{
    if (
$factor == 'r' ) {
        
$pixel->r = 0;
    }
    if (
$factor == 'g' ) {
        
$pixel->g = 0;
    }
    if (
$factor == 'b' ) {
        
$pixel->b = 0;
    }
    if (
$factor == 'rb' || $factor == 'br') {
        
$pixel->r = 0;
        
$pixel->b = 0;
    }
    if (
$factor == 'rg' || $factor == 'gr') {
        
$pixel->r = 0;
        
$pixel->g = 0;
    }
    if (
$factor == 'bg' || $factor == 'gb') {
        
$pixel->b = 0;
        
$pixel->g = 0;
    }
    return
$pixel;
}

function
maxColor($pixel, $factor)
{
    if (
$factor == 'r' ) {
        
$pixel->r = 255;
    }
    if (
$factor == 'g' ) {
        
$pixel->g = 255;
    }
    if (
$factor == 'b' ) {
        
$pixel->b = 255;
    }
    if (
$factor == 'rb' || $factor == 'br') {
        
$pixel->r = 255;
        
$pixel->b = 255;
    }
    if (
$factor == 'rg' || $factor == 'gr') {
        
$pixel->r = 255;
        
$pixel->g = 255;
    }
    if (
$factor == 'bg' || $factor == 'gb') {
        
$pixel->b = 255;
        
$pixel->g = 255;
    }
    return
$pixel;
}
?>

Результаты:

Удаляем красный
Рис. 11
Удаляем зеленый
Рис. 12
Удаляем синий
Рис. 13
Удаляем красный и зеленый
Рис. 14
Удаляем зеленый и синий
Рис. 15
Удаляем красный и синий
Рис. 16
Насыщаем красный
Рис. 17
Насыщаем зеленый
Рис. 18
Насыщаем синий
Рис. 19
Насыщаем красный и зеленый
Рис. 20
Насыщаем зеленый и синий
Рис. 21
Насыщаем красный и синий
Рис. 22

Делаем негатив

Эта функция очень проста – у вас много красного? Значит сделаем мало. И так далее.

<?php
function negative($pixel)
{
    return new
Pixel(
    
255 - $pixel->g,
    
255 - $pixel->r,
    
255 - $pixel->b
    
);
}
?>

Результат:

Рис. 23

Оттенки серого (Grayscale)

Не знаю, в курсе вы или нет, но оттенок серого получается уравниванием R, G, B каналов. Более темные участки имеют больше насыщения, светлые – меньше.

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

<?php
function greyscale($pixel)
{
    
$pixel_average = ($pixel->r + $pixel->g + $pixel->b) / 3;

    return new
Pixel(
    
$pixel_average,
    
$pixel_average,
    
$pixel_average
    
);
}
?>

Результат:

Рис. 24

Черно-белое

В отличие от оттенков серого, черно-белое изображение имеет только 2 цвета: черный (0,0,0) и белый (255,255,255). $factor мы будем использовать для определения границы того, что считать черным, а что – белым. Простота логики в том, что мы суммируем R+G+B и смотрим, к чему значение ближе – к 255 или к 0. Использование $factor позволит нам внести некоторую гибкость в алгоритм (внести некоторую субъективность):

<?php
function blackAndWhite($pixel, $factor)
{
    
$pixel_total = ($pixel->r + $pixel->g + $pixel->b);

    if (
$pixel_total > (((255 + $factor) / 2) * 3)) {
        
// белый
        
$pixel->r = 255;
        
$pixel->g = 255;
        
$pixel->b = 255;
    } else {
        
$pixel->r = 0;
        
$pixel->g = 0;
        
$pixel->b = 0;
    }

    return
$pixel;
}

?>

Результат ($factor = 20):

Рис. 25

Отсечение

Не знаю, насколько эта функция может оказаться полезной. Она занимается удалением пограничных значений (переходов) цвета, заменя их чистым цветом: если у вас было 5, 155, 250 станет – 0, 155, 255. $factor дает нам гибкость в рисунке. Пока я вижу нужность этой функции для уменьшения размера изображения.

<?php
function clip($pixel, $factor)
{
    if (
$pixel->r > 255 - $factor) {
        
$pixel->r = 255;
    }
    if (
$pixel->r < $factor) {
        
$pixel->r = 0;
    }
    if (
$pixel->g > 255 - $factor) {
        
$pixel->g = 255;
    }
    if (
$pixel->g < $factor) {
        
$pixel->g = 0;
    }
    if (
$pixel->b > 255 - $factor) {
        
$pixel->b = 255;
    }
    if (
$pixel->b < $factor) {
        
$pixel->b = 0;
    }

    return
$pixel;
}
?>

Результат ($factor = 100):

Рис. 26

Корректировка контраста

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

<?php
function getAverageLuminance($image)
{
    
$luminance_running_sum = 0;
    
$x_dimension = imagesx($image);
    
$y_dimension = imagesy($image);
    for (
$x = 0; $x < $x_dimension; $x++) {
        for (
$y = 0; $y < $y_dimension; $y++) {

            
$rgb = imagecolorat($image, $x, $y);
            
$r = ($rgb >> 16) & 0xFF;
            
$g = ($rgb >> 8) & 0xFF;
            
$b = $rgb & 0xFF;

            
$luminance_running_sum += (0.30 * $r) + (0.59 * $g) + (0.11 * $b);

        }

    }
    
$total_pixels = $x_dimension * $y_dimension;
    return
$luminance_running_sum / $total_pixels;
}
?>

Конечное же преобразование контраста очень просто:

<?php
function contrast($pixel, $factor, $average_luminance)
{
    return new
Pixel(
    
$pixel->r * $factor + (1 - $factor) * $average_luminance,
    
$pixel->g * $factor + (1 - $factor) * $average_luminance,
    
$pixel->b * $factor + (1 - $factor) * $average_luminance
    
);
}
?>

Результаты (0.5 и 1.5 соответственно):

Рис. 27 Рис. 28

Соль и перец

Эта функция в целом случайным образом «разбрызгивает» по изображению белые и черные точки.

<?php
function saltAndPepper($pixel, $factor)
{
    
$black = (int)($factor/2 + 1);
    
$white = (int)($factor/2 - 1);
    
$random = mt_rand(0, $factor);
    
$new_channel = false;
    if (
$random == $black) {
        
$new_channel = 0;
    }
    if (
$random == $white) {
        
$new_channel = 255;
    }
    if (
is_int($new_channel)) {
        return new
Pixel($new_channel, $new_channel, $new_channel);
    } else {
        return
$pixel;
    }
}
?>

Пример ($factor = 20):

Рис. 29

Гамма-коррекция

<?php
function gamma($pixel, $factor)
{
    return new
Pixel(
    
pow($pixel->r / 255, $factor) * 255,
    
pow($pixel->g / 255, $factor) * 255,
    
pow($pixel->b / 255, $factor) * 255
    
);
}
?>

Пример ($factor = 2.2):

Рис. 30

Послесловие

Если вы, экспериментируя с этим классом, изобрели еще какой-либо интересный эффект - опубликуйте свою функцию в комментариях внизу этой страницы и я добавлю ее в эту статью!

Источник: www.kuzma.russofile.ru

Ссылки по теме
Внутренние функции
Обработка строк в РНР
PHP и всё такое...
Пишем PHP код, устойчивый к ошибкам
Полезные скрипты на PHP
Почтовые функции в РНР
Полезные функции для работы с файловой системой
 

Компьютерная документация от А до Я - Главная

 

 
Интересное в сети
 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.
 
Rambler's Top100