Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何使用GD检查图像是否具有透明度?_Php_Image Processing_Gd - Fatal编程技术网

Php 如何使用GD检查图像是否具有透明度?

Php 如何使用GD检查图像是否具有透明度?,php,image-processing,gd,Php,Image Processing,Gd,如何使用php的GD库检查图像是否具有透明像素?看起来您无法一眼就检测到透明 建议在处理真彩色图像时得到的整数实际上可以移动四倍,第四个是alpha通道(其他三个是红色、绿色和蓝色)。因此,给定$x和$y处的任何像素位置,可以使用以下方法检测alpha: $rgba = imagecolorat($im,$x,$y); $alpha = ($rgba & 0x7F000000) >> 24; $red = ($rgba & 0xFF0000) >> 16;

如何使用php的GD库检查图像是否具有透明像素?

看起来您无法一眼就检测到透明

建议在处理真彩色图像时得到的整数实际上可以移动四倍,第四个是alpha通道(其他三个是红色、绿色和蓝色)。因此,给定
$x
$y
处的任何像素位置,可以使用以下方法检测alpha:

$rgba = imagecolorat($im,$x,$y);
$alpha = ($rgba & 0x7F000000) >> 24;
$red = ($rgba & 0xFF0000) >> 16;
$green = ($rgba & 0x00FF00) >> 8;
$blue = ($rgba & 0x0000FF);
127的
$alpha
显然是完全透明的,而零则是完全不透明的


不幸的是,您可能需要处理图像中的每个像素,以便找到一个透明的像素,然后这只适用于真彩色图像。否则,
imagecolorat
将返回一个颜色索引,您必须使用该索引进行查找,该索引实际上返回一个带有alpha值的数组。

我知道这是一个旧的索引,但我刚刚在PHP文档的注释中找到了它。()

以下是确定PNG图像是否包含alpha的函数:

<?php
    function is_alpha_png($fn){
      return (ord(@file_get_contents($fn, NULL, NULL, 25, 1)) == 6);
    }
?>

PNG图像的颜色类型存储在字节偏移量25处。第25个字节的可能值为:

  • 0-灰度
  • 2-RGB
  • 3-带调色板的RGB
  • 4-灰度+α
  • 6-RGB+α

但仅适用于PNG图像。

函数将检查图像中是否有透明像素,如果有,则返回true

$im = imagecreatefrompng('./transparent.png');
if(check_transparent($im)) {
    echo 'DA';
}
else {
    echo 'NU';
}

function check_transparent($im) {

    $width = imagesx($im); // Get the width of the image
    $height = imagesy($im); // Get the height of the image

    // We run the image pixel by pixel and as soon as we find a transparent pixel we stop and return true.
    for($i = 0; $i < $width; $i++) {
        for($j = 0; $j < $height; $j++) {
            $rgba = imagecolorat($im, $i, $j);
            if(($rgba & 0x7F000000) >> 24) {
                return true;
            }
        }
    }

    // If we dont find any pixel the function will return false.
    return false;
}
$im=imagecreatefrompng('./transparent.png');
如果(勾选透明($im)){
回音“达”;
}
否则{
呼应‘怒’;
}
功能检查透明($im){
$width=imagesx($im);//获取图像的宽度
$height=imagesy($im);//获取图像的高度
//我们逐像素运行图像,一旦找到透明像素,我们停止并返回true。
对于($i=0;$i<$width;$i++){
对于($j=0;$j<$height;$j++){
$rgba=imagecolorat($im,$i,$j);
如果($rgba&0x7F000000)>>24){
返回true;
}
}
}
//如果我们找不到任何像素,函数将返回false。
返回false;
}

这是可以做到的

我已将所有答案和评论合并到一个功能中,该功能应快速可靠:

function hasAlpha($imgdata) {
    $w = imagesx($imgdata);
    $h = imagesy($imgdata);

    if($w>50 || $h>50){ //resize the image to save processing if larger than 50px:
        $thumb = imagecreatetruecolor(10, 10);
        imagealphablending($thumb, FALSE);
        imagecopyresized( $thumb, $imgdata, 0, 0, 0, 0, 10, 10, $w, $h );
        $imgdata = $thumb;
        $w = imagesx($imgdata);
        $h = imagesy($imgdata);
    }
    //run through pixels until transparent pixel is found:
    for($i = 0; $i<$w; $i++) {
        for($j = 0; $j < $h; $j++) {
            $rgba = imagecolorat($imgdata, $i, $j);
            if(($rgba & 0x7F000000) >> 24) return true;
        }
    }
    return false;
}

//SAMPLE USE:
hasAlpha( imagecreatefrompng("myfile.png") );   //returns true if img has transparency
函数hasAlpha($imgdata){
$w=imagesx($imgdata);
$h=imagesy($imgdata);
如果($w>50 | |$h>50){//如果大于50px,请调整图像大小以保存处理:
$thumb=imagecreatetruecolor(10,10);
图像(拇指,假);
imagecopyresized($thumb、$imgdata、0、0、0、10、10、$w、$h);
$imgdata=$thumb;
$w=imagesx($imgdata);
$h=imagesy($imgdata);
}
//运行像素,直到找到透明像素:
对于($i=0;$i>24),返回true;
}
}
返回false;
}
//样本使用:
hasAlpha(imagecreatefrompng(“myfile.png”)//如果img具有透明度,则返回true

我知道这是一个旧线程,但我认为它需要改进,因为通过检查所有像素来遍历一个巨大的png,结果发现它是不透明的,这是浪费时间。所以,在谷歌搜索之后,我找到了他的代码,并在Future的帮助下改进了他的代码,使其更加可靠、快速,并且具有最小的内存印记:

function IsTransparentPng($File){
    //32-bit pngs
    //4 checks for greyscale + alpha and RGB + alpha
    if ((ord(file_get_contents($File, false, null, 25, 1)) & 4)>0){
        return true;
    }
    //8 bit pngs
    $fd=fopen($File, 'r');
    $continue=true;
    $plte=false;
    $trns=false;
    $idat=false;
    while($continue===true){
        $continue=false;
        $line=fread($fd, 1024);
        if ($plte===false){
            $plte=(stripos($line, 'PLTE')!==false);
        }
        if ($trns===false){
            $trns=(stripos($line, 'tRNS')!==false);
        }
        if ($idat===false){
            $idat=(stripos($line, 'IDAT')!==false);
        }
        if ($idat===false and !($plte===true and $trns===true)){
            $continue=true;
        }
    }
    fclose($fd);
    return ($plte===true and $trns===true);
}

cronoklee的函数非常好,但是当我使用它时,我发现了一个bug。它不适用于带有8位托盘的图像。以下是固定变量:

public function hasAlpha($imgdata)
{
    $w = imagesx($imgdata);
    $h = imagesy($imgdata);

    if($w>100 || $h>100){ //resize the image to save processing
        $thumb = imagecreatetruecolor(100, 100);
        imagealphablending($thumb, FALSE);
        imagecopyresized( $thumb, $imgdata, 0, 0, 0, 0, 100, 100, $w, $h );
        $imgdata = $thumb;
        $w = imagesx($imgdata);
        $h = imagesy($imgdata);
    }
    //run through pixels until transparent pixel is found:
    for($i = 0; $i<$w; $i++) {
        for($j = 0; $j < $h; $j++) {
            $ci = imagecolorat($imgdata, $i, $j);
            $rgba = imagecolorsforindex($imgdata, $ci);
            if($rgba['alpha']) { return true; }
        }
    }
    return false;
}
公共函数hasAlpha($imgdata)
{
$w=imagesx($imgdata);
$h=imagesy($imgdata);
如果($w>100 | |$h>100){//调整图像大小以保存处理
$thumb=ImageCreateTureColor(100100);
图像(拇指,假);
imagecopyresized($thumb、$imgdata、0、0、0、100、100、$w、$h);
$imgdata=$thumb;
$w=imagesx($imgdata);
$h=imagesy($imgdata);
}
//运行像素,直到找到透明像素:

对于($i=0;$i这是我检测8-32位透明度的方式。它仅适用于PNG

function detect_transparency($file){

    if(!@getimagesize($file)) return false;

    if(ord(file_get_contents($file, false, null, 25, 1)) & 4) return true;

    $content = file_get_contents($file);
    if(stripos($content,'PLTE') !== false && stripos($content, 'tRNS') !== false) return true;

    return false;
}

改进了cronoklee的函数。删除了每个像素不必要的位移位,减少了误报计数,在函数描述中添加了解释

/**
*估计,若图像有透明像素,它会将图像缩小到64倍
*如有必要,调整大小,并搜索具有非零alpha字节的第一个像素。
*如果图像的不透明度为1%,则会检测到该图像。如果任何8x8像素块的不透明度至少为1%
*一个半透明像素,该块将触发阳性结果。仍有情况,
*如果透明度不明显的图像将被报告为不透明,
*但用单调的背景填充这样的图像几乎总是安全的。
*

*有大小的图标什么样的图像?GIF、PNG-8或PNG-24?没有GD还有其他方法吗?可能,但这个特定的问题都是关于GD的。考虑到你的其他(重复)问题,你已经在使用GD了,所以这不是问题。我的意思是,如果没有GD还有其他方法,那么你不需要检查每一个像素?如果你有Imagick扩展,这个方法看起来可以做到。Imagick扩展是非标准的,我不确定这是否可以通过调用普通的老香草来实现-exec Image Magick。这将不起作用。此值表示特定PNG支持透明度。如果该值表示支持透明度,则仍需要检查它是否实际包含至少一个透明像素。@Jongware你完全正确。不过,我认为这是避免检查每个图像中每个像素的开销的一个好方法。Dep根据您的要求,您可以通过此功能猜测图像是否具有透明度,或者您可以使用它来确定是否需要进一步处理它。解决方案可以是首先使用
is_alpha_png
功能进行检查,然后只对图像进行深度搜索