2016-12-10 26 views
1

在最近的比赛中,我被赋予了从PNG图像文件的alpha通道中提取二进制数据(另一个PNG)的任务。数据的编码方式是,如果我从左上角的每个像素(例如80,78,71,13,10,26,10)读取alpha通道中的值直到特定点,则生成的数据将形成另一个图像。是否可以检索0-255范围内的PNG文件的像素的Alpha值?

最初我试图用PHP完成这个任务,但是我碰到了一个我无法克服的障碍。考虑下面的代码:

function pad($hex){ 
    return strlen($hex) < 2 ? "0$hex" : $hex; 
} 

$channel = ''; 

$image = 'image.png'; 
$ir = imagecreatefrompng($image); 
imagesavealpha($ir, true); 
list($width, $height) = getimagesize($image); 
for ($y = 0; $y < $height; $y++){ 
    for ($x = 0; $x < $width; $x++){ 
     $pixel = imagecolorat($ir, $x, $y); 
     $colors = imagecolorsforindex($ir, $pixel); 
     $a = pad(dechex($colors['alpha'])); 
     $channel.= $a; 
    } 
} 

运行在此之后,我注意到输出不包含PNG神奇的数字,我只是不知道哪里出了问题。经过一番挖掘,我发现$colors['alpha']只包含小于或等于127的值。由于数据已经在编码0-255范围内,所以我找不到解压缩它的方法,最后(成功)改为用node.js解决问题。

所以,我的问题是:是否有任何方式我能读会中,而不是0-127,或者是这是一个硬一个0到255范围内有返回值的PNG文件的alpha通道PHP和/或GD的编码限制?

为了记录,我试图使用($colors['alpha']/127)*255为了尝试伪造错误范围内的值到正确的值,但无济于事。

回答

2

这是GD的限制。根据https://bitbucket.org/libgd/gd-libgd/issues/132/history-behind-7-bit-alpha-component,在GD源,它说:

GD具有只有7 alpha通道的分辨率的位,和127是 透明的,不透明的0。一时的方便,一生的 兼容性。

$image = new Imagick(__DIR__ . DIRECTORY_SEPARATOR . 'image.png'); 
$x = 300; 
$y = 490; 
$pixel = $image->getImagePixelColor($x, $y); 
$colors = $pixel->getColor(true); 
echo 'Alpha value: ' . round($colors['a'] * 255, 0); 

ImageMagick的:

如果安装ImageMagick的PHP扩展,你可以为一个像素(让我们用X = 300和Y = 490说吧)这样得到0-255之间的alpha值: https://www.imagemagick.org

的ImageMagick的PHP(称为Imagick):http://php.net/manual/en/book.imagick.php

+0

这GD值得注意的是有趣@wizard因为我在一块的代码中使用ImageColorAt并奇怪我为什么不得到确切的结果。稍后我会尝试Imagemagick版本,看看我得到了什么。当我写它时,Imagick不可用,使用ImageColorAt比使用exec()的Imagemagick调用更容易。我想我应该更新我的代码,因为自从我编写代码以来,已经发生了很多变化! – Bonzo

+0

我实际上遍历了错误的图像,所以这个解决方案一开始并不起作用,但是修复了'for'循环之后,脚本正好返回了我所需要的。谢谢你的答案。 – SeinopSys

+0

尝试关闭imagealphablending。 '$ img = imagecreatefrompng('image.png');' 'imagealphablending($ img,false);' 'imagesavealpha($ img,true); ' –

-1

在您的代码:

list($width, $height) = getimagesize($image); 
  • 引用未在代码中定义的变量'$ image'。
  • 使用getimagesize意味着$ image是一个文件名。
  • 所以这行从文件名获得宽度和高度。

当我测试它时,这行打破了代码。 你已经有了答案,但这是为了后代。 考虑的代码,我觉得:

$width=imagesx ($ir); 
$height=imagesy ($ir); 

会更合乎逻辑的(和实际工作)

+0

当我修剪这个问题的实际代码时,这个问题留在了那里,我现在修复了它。 – SeinopSys

相关问题