尽管参数正确,但从参数错误的 powershell 调用 GetPixel

Calling GetPixel from powershell with param error despite correct params

下面的代码片段是调试器的输出。

Exception calling "GetPixel" with "2" argument(s): "Parameter must be positive and < Height.
Parameter name: y"
At C:\dropbox\Workspace\PowerShellTest\mapGenerator\mapGenerator.ps1:51 char:16
+             if(($map.GetPixel($x, ($y+1)) -eq "ff000000") -or ($map.GetPixel(($x ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Hit Line breakpoint on 'C:\dropbox\Workspace\PowerShellTest\mapGenerator\mapGenerator.ps1:51'


[DBG]: PS C:\dropbox\Workspace\PowerShellTest\mapGenerator>> $y
5

[DBG]: PS C:\dropbox\Workspace\PowerShellTest\mapGenerator>> $map.Height
7

我根本没有收到此错误消息。

"Parameter must be positive and < Height."

好的。但是参数是 (5+1),所以是正数,而参数是 (5+1),所以 <7

MCVE代码

编辑 1: 删除了 MCVE 代码 - 我在 MCVE 中发现了一个错误,删除后,错误消息也消失了。现在回头看看我原来的代码有没有同样的错误。

编辑 2:这真令人气愤。我为 $x 和 $y 值插入了一个写入输出,只是为了确保我没有任何错误值(例如,检查坐标为 0 的像素下方,或坐标为 map.height 的像素上方 插入写输出使其余代码运行正确。删除写输出使代码再次停止工作。写输出是否在幕后强制执行某些操作?

编辑 3:制作保留这种奇怪行为的 MCVE 非常困难,所以我会给你它发生的脚本。

function markCoastline ($landArray, $map)
{
       foreach ($square in $landArray)
    {

        $x = $square[0]
        $y = $square[1]

        $top = ($y -eq $map.Height-1)
        $bot = ($y -eq 0)
        $lef = ($x -eq 0)
        $rig = ($x -eq $map.Width-1)



        Write-Output $x
        Write-Output $y


        if(     $bot -and $left)
        {
            if(($map.GetPixel($x, ($y+1)).Name -eq "ff000000")-or ($map.GetPixel(($x+1), $y).Name -eq "ff000000"))
            {
                $map.SetPixel($x, $y, "lime")
            }
        }
        elseif( $top -and $left)
        {
            if(($map.GetPixel(($x+1), $y).Name -eq "ff000000") -or ($map.GetPixel($x, ($y-1)).Name -eq "ff000000"))
            {
                $map.SetPixel($x, $y, "lime")
            }
        }
        elseif( $bot -and $rig)
        {
            if(($map.GetPixel(($x-1), $y).Name -eq "ff000000") -or ($map.GetPixel($x, ($y+1)).Name -eq "ff000000"))
            {
                $map.SetPixel($x, $y, "lime")
            }
        }
        elseif( $top -and $rig)
        {
            if(($map.GetPixel(($x-1), $y).Name -eq "ff000000") -or ($map.GetPixel($x, ($y-1)).Name -eq "ff000000"))
            {
                $map.SetPixel($x, $y, "lime")
            }
        }
        elseif(  $lef)
        {
            if(($map.GetPixel($x, ($y+1)).Name -eq "ff000000") -or ($map.GetPixel(($x+1), $y).Name -eq "ff000000") -or ($map.GetPixel($x, ($y-1)).Name -eq "ff000000"))
            {
                $map.SetPixel($x, $y, "lime")
            }
        }
        elseif(  $bot)
        {
            if(($map.GetPixel($x, ($y+1)).Name -eq "ff000000") -or ($map.GetPixel(($x+1), $y).Name -eq "ff000000") -or ($map.GetPixel(($x-1), $y).Name -eq "ff000000"))
            {
                $map.SetPixel($x, $y, "lime")
            }            
        }
        elseif(  $rig)
        {
            if(($map.GetPixel($x, ($y+1)).Name -eq "ff000000")-or ($map.GetPixel(($x-1), $y).Name -eq "ff000000") -or ($map.GetPixel($x, ($y-1)).Name -eq "ff000000"))
            {
                $map.SetPixel($x, $y, "lime")
            }
        }
        elseif(  $top)
        {
            if(($map.GetPixel(($x+1), $y).Name -eq "ff000000") -or ($map.GetPixel(($x-1), $y).Name -eq "ff000000") -or ($map.GetPixel($x, ($y-1)).Name -eq "ff000000"))
            {
                $map.SetPixel($x, $y, "lime")
            }
        }
        else
        {
            if(($map.GetPixel($x, ($y+1)).Name -eq "ff000000") -or ($map.GetPixel(($x+1), $y).Name -eq "ff000000") -or ($map.GetPixel(($x-1), $y).Name -eq "ff000000") -or ($map.GetPixel($x, ($y-1)).Name -eq "ff000000"))
            {
                $map.SetPixel($x, $y, "lime")
            }
        }
    }
}

#First, get a BMP image
$openFile = New-Object -TypeName System.Windows.Forms.OpenFileDialog
    $openFile.AddExtension = $true
    $openFile.Filter = 'Bitmap Picture (*.bmp)|*.bmp|All Files|*.*'
    $openFile.Multiselect = $false
    $openFile.FilterIndex = 0
    $openFile.InitialDirectory = "$HOME\Documents"
    $openFile.RestoreDirectory = $true
    $openFile.ShowReadOnly = $true
    $openFile.ReadOnlyChecked = $false
    $openFile.Title = 'Select a seed picture (BMP only)'
$openFile.showDialog()
$map = New-Object System.Drawing.Bitmap($openFile.Filename)

$landPixels = @()
$oceanPixels = @()


#Second: Find land/ocean
for ($x = 0; $x -lt $map.Width; $x++)
{
    for ($y = 0; $y -lt $map.Height; $y++)
    {
        $current = $map.GetPixel($x, $y)

        if($current.Name -eq "ff000000")
        {
            $ocean = @($x, $y)
            $oceanPixels += , $ocean
        }
        else
        {
            $land = @($x, $y)
            $landPixels += , $land
        }
    }
}


#Third, paint coastline green:

markCoastline $landPixels $map

$map.save("b8fcf4351caf4b00af8eb0fa2e5bc17a.bmp")

第 16 行和第 17 行有一个写入输出。删除它们,脚本给出了上面提到的原始问题 - 声称 $y 不适合作为 GetPixel 函数的参数。保持它和代码 运行 完全符合预期。

在您的代码中有两个地方使用 $left 而不是 $lef。不管 Write-Output,我仍然收到该错误消息。错误消息只是隐藏在所有输出之下,但它仍然在这里。

我建议您在调试代码时使用 Set-StrictMode -Version Latest$ErrorActionPreference='Inquire'。用它们更容易发现错误。

P.S.
不使用数组加法,而是重新分配数组或每次加法,而是使用列表:

$landPixels = New-Object System.Collections.Generic.List[object]
$oceanPixels = New-Object System.Collections.Generic.List[object]

for ($x = 0; $x -lt $map.Width; $x++)
{
    for ($y = 0; $y -lt $map.Height; $y++)
    {
        $current = $map.GetPixel($x, $y)

        if($current.Name -eq "ff000000")
        {
            $oceanPixels.Add(($x,$y))
        }
        else
        {
            $landPixels.Add(($x,$y))
        }
    }
}

P.P.S.

$x,$y = $square

P.P.P.S

if(
    (($y+1 -lt $map.Height) -and ($map.GetPixel($x, ($y+1)).Name -eq "ff000000")) -or
    (($y-1 -gt 0)           -and ($map.GetPixel($x, ($y-1)).Name -eq "ff000000")) -or
    (($x+1 -lt $map.Width)  -and ($map.GetPixel(($x+1), $y).Name -eq "ff000000")) -or
    (($x-1 -gt 0)           -and ($map.GetPixel(($x-1), $y).Name -eq "ff000000"))
)
{
    $map.SetPixel($x, $y, "lime")
}