2017-02-10 10 views
1

this SO answerにC#メソッドがあり、画像に透明性があるかどうかを検出しました。私はこのメソッドをPowerShellに変換しようとしています。InteropServices.Marshal.Copy C#メソッドから変換されたPowerShellスクリプトで常にゼロ

残念ながら、私はそれを動作させるように見えることはできません。 Marshal.Copyの部分がすべて正常に機能しているように見えます.の配列は、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画像のみで動作する」というコメントの1つで警告に耳を傾けましたか?あなたがそうした場合、そのようなイメージを使ってテストを実行したと言わなければなりません。 – Sabuncu

+0

申し訳ありませんが、私はそれを明確にしませんでした。あなたは正しいです、私は32ビットRGBA PNGイメージでこれを実行することを意図しました。 PNGタイプ0,2,3では、tRNSチャンクをチェックし、タイプ4のImageMagickでチェックします(遅いですが)私の場合はまれですので大丈夫です。私はこれがImageMagickを使うよりも速くなることを期待していましたが、まだ動作させていません。 – Bighead

答えて

1

あなたのコードはそのままで動作しますが(Win7ではPS5.1)、問題があります。 一部のピクチャはアルファチャンネルを持っていないので、各ピクセルはイメージバイトだけで構成され、アルファは含まれません。バイト数もフォーマットによって異なります.1,1,2,3,4,6,8バイト以下です。

ビットマスクフラグとしてチェックピクセルフォーマット:

$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

は今、私は同様に他の画像のためにそれを使用することができ、提案をありがとう!そして、ついにそれは何とか今働いている!ここでは、誰もがGoogleの検索でそれにつまずいた場合の完全な作業関数+ wOxxOmの提案です。私は何年にもわたって何度も答えを探していたことを知っています。これは本当にすばらしい人との素晴らしいサイトです。

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 
} 

後で問題を引き起こしたビットマップを破棄するのを忘れてしまったため編集されました。

関連する問題