The code snippet below is the debugger output.
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
I do not get this error message at all.
"Parameter must be positive and < Height."
Ok. But parameter is (5+1), so positive, and (5+1), so <7
MCVE Code
EDIT 1: MCVE code removed - I found an error in the MCVE which, when removed, also got rid of the error message. Now to go back and see if I have the same error in the original code.
EDIT 2: This is infuriating. I inserted a write-output for the $x and $y values, just to make sure I didn't have any with bad values (E.g. checking below a pixel with coordinate 0, or above a pixel with coordinate map.height Inserting the write-output made the rest of the code run correctly. And removing the write-output makes the code stop working again. Does write-output coerce something behind the scenes?
EDIT 3: It is very difficult to make an MCVE that retains this weird behavior, so I'll give you the script it happens in.
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")
There's a write-output on lines 16 and 17. Remove those and the script gives the original problem mentioned above - claims $y doesn't fit as a parameter for the GetPixel function. Keep it in and the code runs exactly as intended.
In two places in your code you use $left
instead of $lef
. And I still got that error message regardless of Write-Output
. Error message just got buried under all that output, but it still here.
I recommend to use Set-StrictMode -Version Latest
and $ErrorActionPreference='Inquire'
when you are debugging your code. It is easier to spot error with them.
P.S.
Does not use array addition it reallocate array or every addition, use lists instead:
$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")
}