如何使用GD获取像素的正确RGB值?

3
我有一个4x1像素的png图片,最左边的像素是白色(#ffffff),第二个像素是红色(#ff0000),第三个像素是绿色(#00ff00),最右边的像素是蓝色(#0000ff),在这里几乎看不见:enter image description here
使用下面的perl脚本,我尝试读取每个像素的rgb值:
use warnings;
use strict;

use GD;

my $image = new GD::Image('white-red-green-blue.png') or die;

for (my $x=0; $x<4; $x++) {
  my $index = $image->getPixel($x, 0);
  my ($r,$g,$b) = $image->rgb($index);

  printf "%3d %3d %3d\n", $r, $g, $b;
}

令我十分惊讶的是,它打印了。
252 254 252
252   2   4
  4 254   4
  4   2 252

然而我预期的情况是

255 255 255
255   0   0
  0 255   0
  0   0 255

为什么脚本报告错误的rgb值,我应该如何让它报告正确的值?
编辑:根据mpapec的问题,base64 white-red-green-blue.png的输出为:
iVBORw0KGgoAAAANSUhEUgAAAAQAAAABCAIAAAB2XpiaAAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASSURBVBhXY/gPBAwMDEDM8B8AL90F
+8V5iZQAAAAASUVORK5CYII=

编辑 II 根据 dgw 的建议,我也尝试了my $image = newFromPng GD::Image('white-red-green-blue.png') or die; 但结果相同。

更新:我已经尝试使用GD代替Image::Magick进行相同的操作:

use warnings;
use strict;

use Image::Magick;

my $image = Image::Magick->new or die;
my $read = $image -> Read('white-red-green-blue.png');

for (my $x=0; $x<4; $x++) {

  my @pixels = $image->GetPixels(
      width     => 1,
      height    => 1,
      x         => $x,
      y         => 0,
      map       =>'RGB',
      #normalize => 1
  );

  printf "%3d %3d %3d\n", $pixels[0] / 256, $pixels[1] / 256, $pixels[2] / 256;

}

而且,可能并不令人惊讶的是,它打印了预期的结果。
255 255 255
255   0   0
  0 255   0
  0   0 255

你尝试过使用 newFromPng 而不是 new 吗? - dgw
2个回答

3

更新

如果您按照以下步骤,它可以正常运行:

GD::Image->trueColor(1);

在开始使用GD之前,我认为可能是一个图像采用了调色板的方式,而另一个则没有。请参见下面的示例:

enter image description here

原始回答

在我的iMac上运行良好。我是通过ImageMagick生成该图像的,方法如下:

convert -size 1x1! xc:rgb\(255,255,255\) xc:rgb\(255,0,0\) xc:rgb\(0,255,0\) xc:rgb\(0,0,255\) +append wrgb.png

./go.pl
255 255 255
255   0   0
0 255   0
0   0 255

我怀疑您的图像未被正确生成。

请再看一下 - 我觉得我解决了这个问题。 - Mark Setchell
GD::Image->trueColor(1); 做到了。非常感谢! - René Nyffenegger
@RenéNyffenegger 这很有趣,但仍然存在这样一个事实,即您可以在调色板中使用“纯”颜色而不必诉诸于 trueColor - mpapec

2

您的原始图像并不是纯RGB格式,但如果需要,可以生成一个纯RGB格式的图像。

use warnings;
use strict;

use GD;

my $image = new GD::Image('white-red-green-blue.png') or die;
my @c = (
  [255,255,255],
  [255,0,0],
  [0,255,0],
  [0,0,255],
);
for my $x (0 .. 3) {
  ##
  $image->setPixel(
    $x,0, $image->colorAllocate(@{ $c[$x] })
  );
  ##
  my $index = $image->getPixel($x, 0);
  my ($r,$g,$b) = $image->rgb($index);

  printf "%3d %3d %3d\n", $r, $g, $b;
}

输出

255 255 255
255   0   0
  0 255   0
  0   0 255

echo 'iVBORw0KGgoAAAANSUhEUgAAAAQAAAABBAMAAAALEhL+AAAAGFBMVEUEAvwE/gT8AgT8/vz/////
AAAA/wAAAP/i4quSAAAAC0lEQVQImWNwTQcAAPQArQCZcI0AAAAASUVORK5CYII=' |
base64 -d > new.png

问题是:如果我用图像程序打开我的“不太纯净的图像”并使用“吸管”选择颜色,那么颜色就是纯净的(255/255/255等)。我真的不明白这里发生了什么。 - René Nyffenegger
@RenéNyffenegger 我会质疑你的图像程序。new.png应该在Perl和'pipette'中给出相同的RGB结果。 - mpapec
尝试发布您的图片 - 然后我们就可以亲眼看到了。 - Mark Setchell
@MarkSetchell 我已经发布了那张图片。由于它只有4x1像素大小,几乎是看不见的,在问题的 almost invisible here: 后面,看起来像省略号。图片链接是:http://i.stack.imgur.com/u5VW5.png - René Nyffenegger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接