使用 powershell 更快地处理 get/set 像素
Faster way to do get/set pixel with powershell
所以我得到了两个函数,一个分析图像是否为灰度,另一个将图像转换为灰度。这些使用 .NET System.Drawing.Bitmap GetPixel 和 SetPixel。
它可以工作,但速度很慢,我读到一些关于将位图锁定在内存中以加快工作速度的信息。
在 C# 中找到了一些示例,但由于没有使用 C# 的经验,我有点迷茫。
示例 http://www.vcskicks.com/fast-image-processing2.php
是否可以在 powershell 中执行此操作?
这里是 powershell 中的函数:
Function Test-ImageGrayScale {
$error.clear()
$filename = $image
$image = New-Object System.Drawing.Bitmap $filename
#keep count of the values
$red = 0
$green = 0
$blue = 0
$total = 0
foreach ($x in 0..($image.Width - 1)) {
foreach ($y in 0..($image.Height - 1)) {
$pixelColor = $image.GetPixel($x, $y)
$red += $pixelColor.R
$green += $pixelColor.G
$blue += $pixelColor.B
$total++
}
}
#Calculate average
$red /= $total
$green /= $total
$blue /= $total
if ($red -eq $green -or $green -eq $blue -or $red -eq $blue) {
Write-Output "Image is Grayscale!"
}
else {
Write-Output "Image is in Color!"
}
}
Function Convert-GrayScale {
$filename = Get-ChildItem $image
$image = New-Object System.Drawing.Bitmap $image
# Output Image
$bitmap = New-Object System.Drawing.Bitmap($image.Width, $image.Height)
foreach ($x in 0..($image.Width - 1)) {
foreach ($y in 0..($image.Height - 1)) {
$pixelColor = $image.GetPixel($x, $y)
$red = $pixelColor.R
$green = $pixelColor.G
$blue = $pixelColor.B
$gray = ($red * .2126) + ($green * .7152) + ($blue * .0722)
$bitmap.SetPixel($x, $y, [System.Drawing.Color]::FromArgb($gray, $gray, $gray))
}
}
$global:outFile = $Outpath + "\" + "GrayScale_" + $filename.basename + ".jpg"
$bitmap.Save($global:outFile)
$bitmap.Dispose()
}
这可能会更快:
function ConvertTo-GrayScale {
# adapted from
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
[Alias('FullName')]
[string]$Path
)
$bitmap = [System.Drawing.Bitmap]::FromFile($Path)
$grayBitmap = [System.Drawing.Bitmap]::new($bitmap.Width, $bitmap.Height)
$graphics = [System.Drawing.Graphics]::FromImage($grayBitmap)
$rect = [System.Drawing.Rectangle]::new(0, 0, $bitmap.Width, $bitmap.Height)
$unit = [System.Drawing.GraphicsUnit]::Pixel
# create a grayscale matrix
[single[][]] $matrix = (0.299, 0.299, 0.299, 0, 0),
(0.587, 0.587, 0.587, 0, 0),
(0.114, 0.114, 0.114, 0, 0),
(0, 0, 0, 1, 0),
(0, 0, 0, 0, 1)
$colorMatrix = [System.Drawing.Imaging.ColorMatrix]::new($matrix)
$attributes = [System.Drawing.Imaging.ImageAttributes]::new()
$attributes.SetColorMatrix($colorMatrix)
# draw the original image on to the new one, using the grayscale color matrix
$graphics.DrawImage($bitmap, $rect, 0, 0, $bitmap.Width, $bitmap.Height, $unit, $attributes)
# create a new name for the image by appending `_gray` to the basename
$fileIn = Get-Item -Path $Path
$fileOut = '{0}_gray{1}' -f (Join-Path -Path $fileIn.DirectoryName -ChildPath $fileIn.BaseName), $fileIn.Extension
# save the grayscaled image
$grayBitmap.Save($fileOut)
#clean-up
$graphics.Dispose()
$grayBitmap.Dispose()
$attributes.Dispose()
$bitmap.Dispose()
}
新版本接受一系列文件,因此您可以直接从 Get-ChildItem
:
function ConvertTo-GrayScale {
# adapted from
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[Alias('FullName')]
[string[]]$Path
)
begin {
# create a grayscale matrix
[single[][]] $matrix = (0.299, 0.299, 0.299, 0, 0),
(0.587, 0.587, 0.587, 0, 0),
(0.114, 0.114, 0.114, 0, 0),
(0, 0, 0, 1, 0),
(0, 0, 0, 0, 1)
# to make the colors inverted for a negative image, use
# [single[][]] $matrix = (-1, 0, 0, 0, 0),
# (0, -1, 0, 0, 0),
# (0, 0, -1, 0, 0),
# (0, 0, 0, 1, 0),
# (0, 0, 0, 0, 1)
$colorMatrix = [System.Drawing.Imaging.ColorMatrix]::new($matrix)
$attributes = [System.Drawing.Imaging.ImageAttributes]::new()
$attributes.SetColorMatrix($colorMatrix)
$unit = [System.Drawing.GraphicsUnit]::Pixel
}
process {
foreach ($file in $Path) {
Write-Verbose "Processing file '$file'"
$bitmap = [System.Drawing.Bitmap]::FromFile($file)
$grayBitmap = [System.Drawing.Bitmap]::new($bitmap.Width, $bitmap.Height)
$graphics = [System.Drawing.Graphics]::FromImage($grayBitmap)
$rect = [System.Drawing.Rectangle]::new(0, 0, $bitmap.Width, $bitmap.Height)
# draw the original image on to the new one, using the grayscale color matrix
$graphics.DrawImage($bitmap, $rect, 0, 0, $bitmap.Width, $bitmap.Height, $unit, $attributes)
# create a new name for the image by appending `_gray` to the basename
$fileIn = Get-Item -Path $file
$fileOut = '{0}_gray{1}' -f (Join-Path -Path $fileIn.DirectoryName -ChildPath $fileIn.BaseName), $fileIn.Extension
# save the grayscaled image
Write-Verbose "Saving file '$fileOut'"
$grayBitmap.Save($fileOut)
#clean-up
$graphics.Dispose()
$grayBitmap.Dispose()
$bitmap.Dispose()
}
}
end {
$attributes.Dispose()
}
}
演示:
Get-ChildItem -Path D:\Test -File | ConvertTo-GrayScale -Verbose
所以我得到了两个函数,一个分析图像是否为灰度,另一个将图像转换为灰度。这些使用 .NET System.Drawing.Bitmap GetPixel 和 SetPixel。 它可以工作,但速度很慢,我读到一些关于将位图锁定在内存中以加快工作速度的信息。
在 C# 中找到了一些示例,但由于没有使用 C# 的经验,我有点迷茫。 示例 http://www.vcskicks.com/fast-image-processing2.php
是否可以在 powershell 中执行此操作?
这里是 powershell 中的函数:
Function Test-ImageGrayScale {
$error.clear()
$filename = $image
$image = New-Object System.Drawing.Bitmap $filename
#keep count of the values
$red = 0
$green = 0
$blue = 0
$total = 0
foreach ($x in 0..($image.Width - 1)) {
foreach ($y in 0..($image.Height - 1)) {
$pixelColor = $image.GetPixel($x, $y)
$red += $pixelColor.R
$green += $pixelColor.G
$blue += $pixelColor.B
$total++
}
}
#Calculate average
$red /= $total
$green /= $total
$blue /= $total
if ($red -eq $green -or $green -eq $blue -or $red -eq $blue) {
Write-Output "Image is Grayscale!"
}
else {
Write-Output "Image is in Color!"
}
}
Function Convert-GrayScale {
$filename = Get-ChildItem $image
$image = New-Object System.Drawing.Bitmap $image
# Output Image
$bitmap = New-Object System.Drawing.Bitmap($image.Width, $image.Height)
foreach ($x in 0..($image.Width - 1)) {
foreach ($y in 0..($image.Height - 1)) {
$pixelColor = $image.GetPixel($x, $y)
$red = $pixelColor.R
$green = $pixelColor.G
$blue = $pixelColor.B
$gray = ($red * .2126) + ($green * .7152) + ($blue * .0722)
$bitmap.SetPixel($x, $y, [System.Drawing.Color]::FromArgb($gray, $gray, $gray))
}
}
$global:outFile = $Outpath + "\" + "GrayScale_" + $filename.basename + ".jpg"
$bitmap.Save($global:outFile)
$bitmap.Dispose()
}
这可能会更快:
function ConvertTo-GrayScale {
# adapted from
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
[Alias('FullName')]
[string]$Path
)
$bitmap = [System.Drawing.Bitmap]::FromFile($Path)
$grayBitmap = [System.Drawing.Bitmap]::new($bitmap.Width, $bitmap.Height)
$graphics = [System.Drawing.Graphics]::FromImage($grayBitmap)
$rect = [System.Drawing.Rectangle]::new(0, 0, $bitmap.Width, $bitmap.Height)
$unit = [System.Drawing.GraphicsUnit]::Pixel
# create a grayscale matrix
[single[][]] $matrix = (0.299, 0.299, 0.299, 0, 0),
(0.587, 0.587, 0.587, 0, 0),
(0.114, 0.114, 0.114, 0, 0),
(0, 0, 0, 1, 0),
(0, 0, 0, 0, 1)
$colorMatrix = [System.Drawing.Imaging.ColorMatrix]::new($matrix)
$attributes = [System.Drawing.Imaging.ImageAttributes]::new()
$attributes.SetColorMatrix($colorMatrix)
# draw the original image on to the new one, using the grayscale color matrix
$graphics.DrawImage($bitmap, $rect, 0, 0, $bitmap.Width, $bitmap.Height, $unit, $attributes)
# create a new name for the image by appending `_gray` to the basename
$fileIn = Get-Item -Path $Path
$fileOut = '{0}_gray{1}' -f (Join-Path -Path $fileIn.DirectoryName -ChildPath $fileIn.BaseName), $fileIn.Extension
# save the grayscaled image
$grayBitmap.Save($fileOut)
#clean-up
$graphics.Dispose()
$grayBitmap.Dispose()
$attributes.Dispose()
$bitmap.Dispose()
}
新版本接受一系列文件,因此您可以直接从 Get-ChildItem
:
function ConvertTo-GrayScale {
# adapted from
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[Alias('FullName')]
[string[]]$Path
)
begin {
# create a grayscale matrix
[single[][]] $matrix = (0.299, 0.299, 0.299, 0, 0),
(0.587, 0.587, 0.587, 0, 0),
(0.114, 0.114, 0.114, 0, 0),
(0, 0, 0, 1, 0),
(0, 0, 0, 0, 1)
# to make the colors inverted for a negative image, use
# [single[][]] $matrix = (-1, 0, 0, 0, 0),
# (0, -1, 0, 0, 0),
# (0, 0, -1, 0, 0),
# (0, 0, 0, 1, 0),
# (0, 0, 0, 0, 1)
$colorMatrix = [System.Drawing.Imaging.ColorMatrix]::new($matrix)
$attributes = [System.Drawing.Imaging.ImageAttributes]::new()
$attributes.SetColorMatrix($colorMatrix)
$unit = [System.Drawing.GraphicsUnit]::Pixel
}
process {
foreach ($file in $Path) {
Write-Verbose "Processing file '$file'"
$bitmap = [System.Drawing.Bitmap]::FromFile($file)
$grayBitmap = [System.Drawing.Bitmap]::new($bitmap.Width, $bitmap.Height)
$graphics = [System.Drawing.Graphics]::FromImage($grayBitmap)
$rect = [System.Drawing.Rectangle]::new(0, 0, $bitmap.Width, $bitmap.Height)
# draw the original image on to the new one, using the grayscale color matrix
$graphics.DrawImage($bitmap, $rect, 0, 0, $bitmap.Width, $bitmap.Height, $unit, $attributes)
# create a new name for the image by appending `_gray` to the basename
$fileIn = Get-Item -Path $file
$fileOut = '{0}_gray{1}' -f (Join-Path -Path $fileIn.DirectoryName -ChildPath $fileIn.BaseName), $fileIn.Extension
# save the grayscaled image
Write-Verbose "Saving file '$fileOut'"
$grayBitmap.Save($fileOut)
#clean-up
$graphics.Dispose()
$grayBitmap.Dispose()
$bitmap.Dispose()
}
}
end {
$attributes.Dispose()
}
}
演示:
Get-ChildItem -Path D:\Test -File | ConvertTo-GrayScale -Verbose