2011-03-31 93 views

回答

4

它看起来并不像您可以一眼即可检测透明度。

The comments on the imagecolorat manual page建议使用真彩色图像时产生的整数实际上可以总共移动四次,第四个是alpha通道(其他三个是红色,绿色和蓝色)。因此,在$x$y给出的任何像素位置,则可以使用检测阿尔法:

$rgba = imagecolorat($im,$x,$y); 
$alpha = ($rgba & 0x7F000000) >> 24; 
$red = ($rgba & 0xFF0000) >> 16; 
$green = ($rgba & 0x00FF00) >> 8; 
$blue = ($rgba & 0x0000FF); 

An的127 $alpha显然是完全透明的,而零是完全不透明的。

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

+0

有没有其他方式没有GD? – 2011-04-03 14:57:59

+2

也许,但这个*特定*问题都是关于GD。考虑到你的其他(重复)问题,你*已经*使用GD,所以这不是问题。 – Charles 2011-04-03 15:02:14

+0

我的意思是,如果没有GD的情况下有其他方式,所以你不需要检查每一个像素? – 2011-04-03 16:20:05

14

我知道这是旧的,但我刚刚在PHP文档的评论中发现了这一点。 (link

这里是确定PNG图像是否包含α或不是功能:

<?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与palett Ë
  • 4 - 灰度+阿尔法
  • 6 - RGB +阿尔法

仅适用于以PNG图像虽然。

+2

这不起作用。该值表示特定的PNG *支持*透明度。如果该值指示它,那么您仍然需要检查它是否实际*包含*至少一个透明像素。 – usr2564301 2014-05-08 22:34:44

+1

@Jongware你是对的。不过,我认为这是避免检查每个图像中每个像素的开销的好方法。根据您的要求,您可以通过此功能猜测图像是否具有透明度,或者可以使用它来确定是否需要进一步处理它。 – 2014-05-16 15:21:43

+1

一个解决方案可能首先检查该is_alpha_png函数,并且只在深度搜索透明像素,如果它是真的 – 2014-08-15 09:23:37

2

漂亮的海峡转发功能,它会检查图像中是否有透明像素,如果是,它会返回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; 
} 
4

它可以做到!

我已经合并所有的答案和注释成一个函数,它应该是快速&可靠:

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 
+0

如果图像是1px乘以10000px,那么您的函数将不必要地调整大小,仍然是一个非常小的图像。我建议你除以高度的宽度,并检查比例,而不是..或者只是检查实际文件大小..还有,如果有说一个透明的像素,你可以通过压缩图像压缩到10x10 ..你可能想要考虑将其做大一点,并可能保留宽高比。除此之外,做得好! +1 – 2015-12-01 21:43:08

0

我知道这是一个古老的线程,但在我看来,它需要因为通过一个巨大的改善行走png通过检查所有像素来发现它不透明是浪费时间。因此,一些googleing后,我发现Jon Fox's Blog,我提高了自己与W3C PNG Specification的帮助代码进一步可靠,快速,对内存的印记最低:

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); 
} 
0

cronoklee的功能是很不错的,但是当我使用它发现了一个错误。它不适用于具有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; 
}