2017-02-10 64 views
1

我在this SO answer中发现了一个C#方法来检测图像是否具有透明度。我试图将该方法转换为PowerShell。InteropServices.Marshal.Copy在C#方法转换的PowerShell脚本中始终为零

不幸的是,我似乎无法得到它的工作。在Marshal.Copy部分之前,一切似乎都正常工作,并且所有的值都被正确填充,除了Bytes数组,即使在Marshal.Copy之后也是全零。

以下是原文的代码在C#:

public bool IsAlphaBitmap(ref System.Drawing.Imaging.BitmapData BmpData) 
{ 
    byte[] Bytes = new byte[BmpData.Height * BmpData.Stride]; 
    Marshal.Copy(BmpData.Scan0, Bytes, 0, Bytes.Length); 
    for (p = 3; p < Bytes.Length; p += 4) { 
     if (Bytes[p] != 255) return true; 
    } 
    return false; 
} 

这是PowerShell的版本,我至今(不工作):

function IsAlphaBitMap([string]$imagepath) 
{ 
    $BitMap = New-Object System.Drawing.BitMap($imagepath) 
    $Rect = New-Object System.Drawing.Rectangle(0, 0, $BitMap.Width, $BitMap.Height) 
    $BmpData = [System.Drawing.Imaging.BitmapData]$BitMap.LockBits($Rect, [System.Drawing.Imaging.ImageLockMode]::ReadWrite, $BitMap.PixelFormat) 

    $Bytes = New-Object byte[] ($BmpData.Height * $BmpData.Stride) 
    [System.Runtime.InteropServices.Marshal]::Copy($BmpData.Scan0, $Bytes, 0, $Bytes.Length) 
    for($p=3 ; $p -lt $Bytes.Length ; $p+=4) 
    { 
     if ($Bytes[$p] -ne 255) { write-host $Bytes[$p] } # { return $true } 
    } 
    return $false 
} 

我没有使用一个write-host循环而不是返回值,所以我可以读取每次迭代的输出,它总是为零。任何人都可以看到我错了哪里?

+0

即使输出为零行,您也可以考虑添加'write-host'的输出。另外,你是否注意到其中一条评论中提到“这只适用于32 bpp图像”的警告?如果你这样做,你应该说你使用这样的图像进行测试。 – Sabuncu

+0

对不起,我没有说清楚。你是对的,我只是打算在32位RGBA PNG图像上运行它。对于PNG类型0,2和3,我检查tRNS块,然后输入4我检查ImageMagick(它很慢!),但在我的情况很少见,所以没关系。我希望这会比使用ImageMagick快,但我还没有得到它的工作。 – Bighead

回答

1

您的代码对我来说是原样(Win7上的PS5.1),但它有问题。 有些图片没有alpha通道,因此每个像素仅包含图像字节,不包含alpha。字节数也根据格式不同而不同:小于1,1,2,3,4,6,8字节。

检查的PixelFormat作为一个位掩码标志:

$BitMap = [Drawing.BitMap]$imagepath 
if ($BitMap.PixelFormat.value__ -band [Drawing.Imaging.PixelFormat]::Alpha -eq 0) { 
    return $false 
} 

,并使用实际像素长度:

$pixelBytes = [Drawing.Image]::GetPixelFormatSize($bitmap.PixelFormat) -shr 3 
if (!$pixelBytes) { 
    Write-Warning 'Sorry, 2lazy2support paletted images with pixels less than 8 bits' 
    return $null 
} 

$len = $Bytes.Length 
for ($p = $pixelBytes - 1; $p -lt $len; $p += $pixelBytes) { 
    if ($Bytes[$p] -ne 255) { 
     return $true 
    } 
} 
+0

谢谢你的建议,这是非常有用的,并延长了我的这个功能的原始目标。 – Bighead

0

谢谢你的建议,现在我可以将其用于其他图像以及!现在终于可以工作了!这是完整的工作功能+ wOxxOm的建议,以防有人在Google搜索中绊倒它。我知道我多年来在寻找答案时结束了很多次,这真是一个伟大的人的伟大网站。

function IsAlphaBitMap([string]$imagepath) 
{ 
    $BitMap = [Drawing.BitMap]$imagepath 
    if (($BitMap.PixelFormat.value__ -band [Drawing.Imaging.PixelFormat]::Alpha) -eq 0) 
    { 
     return $false 
    } 
    $pixelBytes = [Drawing.Image]::GetPixelFormatSize($BitMap.PixelFormat) -shr 3 
    if (!$pixelBytes) 
    { 
     Write-Warning 'Sorry, 2lazy2support paletted images with pixels less than 8 bits' 
     return $null 
    } 
    $Rect = New-Object System.Drawing.Rectangle(0, 0, $BitMap.Width, $BitMap.Height) 
    $BmpData = [Drawing.Imaging.BitmapData]$BitMap.LockBits($Rect, [System.Drawing.Imaging.ImageLockMode]::ReadWrite, $BitMap.PixelFormat) 
    $Bytes = New-Object byte[] ($BmpData.Height * $BmpData.Stride) 
    [System.Runtime.InteropServices.Marshal]::Copy($BmpData.Scan0, $Bytes, 0, $Bytes.Length) 
    $BitMap.Dispose() 

    $len = $Bytes.Length 
    for($p = ($pixelBytes - 1) ; $p -lt $len ; $p += $pixelBytes) 
    { 
     if ($Bytes[$p] -ne 255) 
     { 
      return $true 
     } 
    } 
    return $false 
} 

编辑,因为我忘了处理后来引起问题的位图。