.net - 使用 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 https://stackoverflow.com/questions/2038865/accelerating-bitmap-grayscale-conversion-is-openmp-an-option-in-c
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 https://stackoverflow.com/questions/2038865/accelerating-bitmap-grayscale-conversion-is-openmp-an-option-in-c
[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
推荐阅读
- asp.net-core - 为单元测试 Signalr .NetCore 消息集线器模拟 Context.ConnectionId
- hyperledger-fabric - 从客户端发送查询请求时出错:没有可查询的对等方
- r - 除第一列外,删除所有 NA 的行
- php - 无法插入数据库 - PHP
- arduino - 如何用 esp32 测量 Lipo 或 lifepo4 电池
- excel - 如何以特定顺序使用多个范围构建新范围?
- c# - 同类型的一对一关系实体
- c# - 从浮点数转换为整数权重
- sql-server - 如何查找受 SQL 影响的新记录集的表列表?
- cucumber - Poltergeist JS/Headless Chrome - 切换到离线模式