Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying pixels in an image using Perl

Tags:

perl

Suppose I want to take one picture, move all of its pixels one pixel to the right and one to the left, and save it. I tried this code:

my $image_file = "a.jpg";
my $im = GD::Image->newFromJpeg($image_file);
my ($width, $height) = $im->getBounds();
my $outim = new GD::Image($width, $height);

foreach my $x (1..$width)
{
    foreach my $y (1..$height)
    {
        my $index = $im->getPixel($x-1,$y-1);
        my ($r,$g,$b) = $im->rgb($index);
        my $color = $outim->colorAllocate($r,$g,$b);
        $outim->setPixel($x,$y,$color);
    }
}
%printing the picture...

That doesn't do the trick; it draws all pixels, except those in which x=0 or y=0, in one color. Where am I going wrong?

like image 923
ronash Avatar asked Nov 26 '25 10:11

ronash


2 Answers

Look in the docs:

Images created by reading JPEG images will always be truecolor. To force the image to be palette-based, pass a value of 0 in the optional $truecolor argument.

It's not indexed. Try adding a ,0 to your newFromJpeg call.

From the comments, it seems your next problem is the number of colors to allocate. By default, the indexed image is 8-bit, meaning a maximum number of 256 unique colors (2^8=256). The "simple" workaround is of course to use a truecolor image instead, but that depends on whether you can accept truecolor output.

If not, your next challenge will be to come up with "an optimal" set of 256 colors that will minimize the visible defects in the image itself (see http://en.wikipedia.org/wiki/Color_quantization). That used to be a whole topic in itself that we seldom have to worry about today. If you still have to worry about it, you are probably better off offloading that job to some specialized tool like Imagemagik or similar, rather than try to implement it yourself. Unless you like challenges of course.

like image 65
Marius Kjeldahl Avatar answered Nov 28 '25 23:11

Marius Kjeldahl


Here's a solution using Imager because it's a very nice module and I'm more familiar with it, and it handles image transformations nicely.

use Imager;

my $image_file = "a.jpg";

my $src = Imager->new(file => $image_file) or die Imager->errstr;

my $dest = Imager->new(
    xsize => $src->getwidth() + 1,
    ysize => $src->getheight() + 1,
    channels => $src->getchannels
);

$dest->paste(left => 1, top => 1, src => $src);
$dest->write(file => "b.jpg") or die $dest->errstr;
like image 43
hobbs Avatar answered Nov 28 '25 23:11

hobbs



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!