如何解决获取图像的所有颜色
Add-Type -AssemblyName System.Windows.Forms
$pic = [Drawing.Bitmap]::new("D:\image.png")
$gfx = [Drawing.Graphics]::FromImage($pic)
$pic.GetPixel(1,1).name
如何使用 .NET 方法获取每个像素的颜色?一个一个地拿,真的很慢。我想,有一种正确的方法可以快速做到这一点。
我听说,LockBits
或许能帮上忙,但如果是,我不知道怎么写...
解决方法
你确实可以使用LockBits()
直接访问位图数据:
using namespace System.Drawing
using namespace System.Runtime.InteropServices
# Load PNG file
$pathToFile = "D:\image.png"
$bmp = [Bitmap]::FromFile($pathToFile)
# Lock all the bits (from top left to bottom right)
$bounds = [Rectangle]::new([Point]::Empty,$bmp.Size)
$data = $bmp.LockBits($bounds,'ReadOnly','Format32bppArgb')
# Scan0 is a pointer to the raw bitmap in local memory
# Let's read the ARGB value at 0,0
$px00 = [Marshal]::ReadInt32($data.Scan0,0)
$px00color = [Color]::FromArgb($px00)
请注意,由于 Int32 为 32 位 = 4 字节宽,因此下一个 ARGB 值始终为当前偏移量 + 4。例如读取 0,1 处的像素值:
$px01 = [Marshal]::ReadInt32($data.Scan0,4)
要枚举所有像素值,您可以这样做:
$pixelLength = $bmp.Width * $bmp.Height
$allPixels = for($offset = 0; $offset -lt $pixelLength; $offset++)
{
[Color]::FromArbg([Marshal]::ReadInt32($data.Scan0,$offset * 4))
}
# don't forget to clean up original bitmap
$bmp.UnlockBits($data)
$bmp.Dispose()
如果您正在处理大图像,由于累积了所有像素数据,这仍然会变慢,因此您可能需要专门针对您的用例优化像素收集过程。
假设我们想要识别图像中的前 25 种颜色 - 在这种情况下,我们不需要收集/存储每个单独的像素值,每个不同颜色只需要一个。为此,哈希表(或任何其他类似字典的数据类型)会更有效:
$pathToFile = "D:\image.png"
$top = 25
$bmp = [System.Drawing.Bitmap]::FromFile($file.FullName)
# Create hashtable to keep track of values seen
$counts = @{}
try {
# Lock all bits
$data = $bmp.LockBits([System.Drawing.Rectangle]::new([System.Drawing.Point]::Empty,$bmp.Size),[System.Drawing.Imaging.ImageLockMode]::ReadOnly,[System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
try {
$length = $bmp.Width * $bmp.Height
for($i = 0; $i -lt $length; $i++)
{
$argb = [System.Runtime.InteropServices.Marshal]::ReadInt32($data.Scan0,$i * 4)
# Increase counter per found ARGB value
$counts[$argb]++
}
}
finally{
# Clean up our read-only handle
$bmp.UnlockBits($data)
}
}
finally{
# Clean up source bmp
$bmp.Dispose()
}
# Pick the top 25 values and convert those to [Color]
$topArgbValues = $counts.GetEnumerator() |Sort Value -Descending |Select -First $top
$topArgbValues |Select @{Name='Color';Expression={[System.Drawing.Color]::FromArgb($_.Key)}},@{Name='Count';Expression={$_.Value}}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。