2015-10-15 3 views
5

Я хочу, чтобы получить 1 пиксель (x=3, y=3) и изменить его RGB значения (R от 100 к 101, G от 99 к 100, B от 193 до 194).Как увеличить значение RGB определенного пикселя с помощью Image :: Magic в Perl?

enter image description here

use strict; 
use Image::Magick; 
my $p = new Image::Magick; 
    $p->Read('myfile.jpg'); 

    my $pix = $p->GetPixel(
      width  => 1, 
      height => 1, 
      x   => 3, 
      y   => 3, 
      map  => 'RGB', 
      normalize => 0 
     ); 

    # in $pix RGB value now? 

Как добавить 1 для всех компонентов RGB?

Могу ли я разделить десятичные RGB на 3 значения (r, g, b) и приращение отдельно, , а затем объединить три значения R, G, B в один RGB? :) Как это сделать?

$pix = .... something code here... 

    # make changes 
    $p->SetPixel(
      x  => 3, 
      y  => 3, 
      channel => 'RGB', 
      color => [ $pix ] 
     ); 
    $p->Write ('my_new_file.jpg'); 
+0

Это было весело. :) – simbabque

ответ

5

Это было немного сложно понять, но вот мы идем. Я покажу вам, что я сделал, чтобы получить результат, а не только, как это работает.

Я использую небольшое изображение с начальным цветом (100, 99, 193).

starting image and color

В верхней части моей программы я всегда буду иметь этот код.

use strict; 
use warnings; 
use Data::Printer; 
use Image::Magick; 
my $p = new Image::Magick; 
$p->Read('33141038.jpg'); 

my @pixel = $p->GetPixel(
    x   => 1, 
    y   => 1, 
    map  => 'RGB', 
    normalize => 1, 
); 

Я проверил the documentation at imagemagick.org.. Он связан в Image::Magick on CPAN. Там я искал GetPixel. Это дает две полезные вещи. Одним из них является объяснение, другое an example, которое показывает, что возвращается массив @pixel, а не скаляр, как вы пробовали.

Здесь мы уменьшить интенсивность красного компонента в точке (1,1) наполовину:

@pixels = $image->GetPixel(x=>1,y=>1); 

ОК. Давайте использовать это. У меня уже есть @pixel в моем коде выше. Обратите внимание, что я также включил опцию normalize. Вы можете оставить это как по умолчанию.

p @pixel; 

# [ 
#  [0] 0.392156862745098, 
#  [1] 0.388235294117647, 
#  [2] 0.756862745098039 
# ] 

Так что это поплавки. После некоторого googling я нашел this answer, который имеет дело с чем-то подобным. Это похоже на долю 255. Давайте размножаться. Мы можем изменить вещи в @pixel, назначив $_ в postfix foreach. Это аккуратно.

$_ *= 255 foreach @pixel; 
p @pixel; 

# [ 
#  [0] 100, 
#  [1] 99, 
#  [2] 193 
# ] 

Это то, что мы хотели. Достаточно легко. Давайте добавим по одному.

$_ = ($_ * 255) + 1 foreach @pixel; 
p @pixel; 

# [ 
#  [0] 101, 
#  [1] 100, 
#  [2] 194 
# ] 

Все еще хорошо. Но как мы можем это вернуть? Документы могут что-то сказать о SetPixel в Manipulate section.

цвет => массив значений поплавка
[...]
установить один пиксель. По умолчанию ожидается нормализованное значение пикселей.

Поэтому, по-видимому, нам нужно вернуться к поплавку. Нет проблем.

$_ = (($_ * 255) + 1)/255 foreach @pixel; 
p @pixel; 

# [ 
#  [0] 0.396078431372549, 
#  [1] 0.392156862745098, 
#  [2] 0.76078431372549 
# ] 

Nice. Конечно, мы можем сделать математику немного короче. Результат тот же.

$_ = $_ + 1/255 foreach @pixel; 

Теперь давайте вернемся к изображению.

$p->SetPixel(
    x => 1, 
    y => 1, 
    color => \@pixel, # need the array ref here 
); 

$p->Write('my_new_file.jpg'); 

На скриншоте, я изменил его, чтобы добавить 20 вместо 1 так это заметнее.

New image with +20 including freehand circles

После очистки код выглядит следующим образом.

use strict; 
use warnings; 
use Data::Printer; 
use Image::Magick; 

my $p = new Image::Magick; 
$p->Read('33141038.jpg'); 

my @pixel = $p->GetPixel(
    x => 1, 
    y => 1, 
); 

# increase RGB by 1 each 
$_ = $_ + 1/255 foerach @pixel; 

$p->SetPixel(
    x  => 1, 
    y  => 1, 
    color => \@pixel, 
); 

$p->Write('my_new_file.jpg'); 

Я удалил map и channel аргументы GetPixel и SetPixel в RGB по умолчанию. То же самое для normalize.

+0

Очень исчерпывающий ответ! Извините за плохой английский. –

+0

@Anton Не беспокойтесь о английском. Это прекрасно понять. Я исправил это немного, чтобы улучшить вопрос. Не смотрите на это, как на критику своих навыков. Это одна из вещей, которые мы делаем здесь: попытайтесь улучшить общее качество контента на SO. В конце концов, это коллекция знаний. :) – simbabque

+0

Красиво ответил. +1 –