是否可以在 0-255 范围内检索 PNG 文件像素的 alpha 值?
Is it possible to retrieve the alpha value of a pixel of a PNG file in the 0-255 range?
在最近的比赛中,我的任务是从 PNG 图像文件的 alpha 通道中提取二进制数据(另一个 PNG)。数据的编码方式是,如果我从左上角(例如 80,78,71,13,10,26,10
)读取每个像素的 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 解决了问题。
所以,我的问题是:是否有 任何 方法我可以读取 PNG 文件的 alpha 通道,该通道会返回 0 到 255 范围内的值而不是 0 -127,或者这是 PHP and/or GD 的硬编码限制?
郑重声明,我尝试使用 ($colors['alpha']/127)*255
来尝试将不正确范围内的值伪造为正确的值,但无济于事。
这是GD的限制。根据 https://bitbucket.org/libgd/gd-libgd/issues/132/history-behind-7-bit-alpha-component,在 GD 源中它说:
gd has only 7 bits of alpha channel resolution, and 127 is
transparent, 0 opaque. A moment of convenience, a lifetime of
compatibility.
如果您安装 ImageMagick PHP 扩展,您可以获得像素的 0-255 之间的 alpha 值(假设 x=300 和 y=490),如下所示:
$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: https://www.imagemagick.org
用于 PHP 的 ImageMagick(称为 Imagick):http://php.net/manual/en/book.imagick.php
在您的代码中:
list($width, $height) = getimagesize($image);
- 引用了代码中未定义的变量“$image”。
- 使用 getimagesize 意味着 $image 是一个文件名。
- 所以这一行从文件名中获取宽度和高度。
这一行在我测试时破坏了代码。
您已经有了答案,但这是为了后代。
考虑代码,感觉:
$width=imagesx ($ir);
$height=imagesy ($ir);
会更合乎逻辑(并且实际可行)
在最近的比赛中,我的任务是从 PNG 图像文件的 alpha 通道中提取二进制数据(另一个 PNG)。数据的编码方式是,如果我从左上角(例如 80,78,71,13,10,26,10
)读取每个像素的 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 解决了问题。
所以,我的问题是:是否有 任何 方法我可以读取 PNG 文件的 alpha 通道,该通道会返回 0 到 255 范围内的值而不是 0 -127,或者这是 PHP and/or GD 的硬编码限制?
郑重声明,我尝试使用 ($colors['alpha']/127)*255
来尝试将不正确范围内的值伪造为正确的值,但无济于事。
这是GD的限制。根据 https://bitbucket.org/libgd/gd-libgd/issues/132/history-behind-7-bit-alpha-component,在 GD 源中它说:
gd has only 7 bits of alpha channel resolution, and 127 is transparent, 0 opaque. A moment of convenience, a lifetime of compatibility.
如果您安装 ImageMagick PHP 扩展,您可以获得像素的 0-255 之间的 alpha 值(假设 x=300 和 y=490),如下所示:
$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: https://www.imagemagick.org
用于 PHP 的 ImageMagick(称为 Imagick):http://php.net/manual/en/book.imagick.php
在您的代码中:
list($width, $height) = getimagesize($image);
- 引用了代码中未定义的变量“$image”。
- 使用 getimagesize 意味着 $image 是一个文件名。
- 所以这一行从文件名中获取宽度和高度。
这一行在我测试时破坏了代码。 您已经有了答案,但这是为了后代。 考虑代码,感觉:
$width=imagesx ($ir);
$height=imagesy ($ir);
会更合乎逻辑(并且实际可行)