我有下一个可重复使用的函数来确定图像中灰度的总百分比。它也可以(部分)用于GIF图像。
此代码存在的问题是:
我想将我的代码转换为等效(或更好)的算法,使用WPF类成员来提高其图像处理性能和功能,并且在代码转换过程中修复了我提到的可以解决的问题。
我怎么能这样做?在C#或VB.NET中,选择并不重要。
这是我目前的代码:
VB.NET
Public Shared Function GetGrayScalePercentOfImage(ByVal img As Image) As Double
Select Case img.PixelFormat
Case PixelFormat.Format16bppGrayScale
Return 100.0R
Case Else
Dim pixelCount As Integer = (img.Width * img.Height)
Dim bytesPerPixel As Integer = (Image.GetPixelFormatSize(img.PixelFormat) \ 8)
If (bytesPerPixel <> 3) AndAlso (bytesPerPixel <> 4) Then
Throw New NotImplementedException(message:="Only pixel formats that has 3 or 4 bytes-per-pixel are supported.")
Else
Dim GrayscalePercentList As New List(Of Double)
Dim frameDimension As New FrameDimension(img.FrameDimensionsList(0))
Dim frameCount As Integer = img.GetFrameCount(frameDimension)
For frameIndex As Integer = 0 To (frameCount - 1)
img.SelectActiveFrame(frameDimension, frameIndex)
' Lock the bitmap's bits.
Dim bmp As Bitmap = DirectCast(img, Bitmap)
Dim rect As New Rectangle(Point.Empty, bmp.Size)
Dim data As BitmapData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat)
' Get the address of the first line.
Dim ptr As IntPtr = data.Scan0
' Declare an array to hold the bytes of the bitmap.
Dim numBytes As Integer = (data.Stride * bmp.Height)
Dim rgbValues As Byte() = New Byte(numBytes - 1) {}
' Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, numBytes)
' Unlock the bitmap's bits.
bmp.UnlockBits(data)
' Iterate the pixels.
Dim grayscalePixelCount As Long ' of current frame.
For pixelIndex As Integer = 0 To (rgbValues.Length - bytesPerPixel) Step bytesPerPixel
Dim c As Color = Color.FromArgb(red:=rgbValues(pixelIndex + 2),
green:=rgbValues(pixelIndex + 1),
blue:=rgbValues(pixelIndex))
If (c.R = c.G) AndAlso (c.G = c.B) AndAlso (c.B = c.R) Then
grayscalePixelCount += 1
End If
Next pixelIndex
Dim frameGrayscalePercent As Double = ((grayscalePixelCount / pixelCount) * 100)
GrayscalePercentList.Add(frameGrayscalePercent)
grayscalePixelCount = 0
Next frameIndex
Return (GrayscalePercentList.Sum() / frameCount)
End If
End Select
End Function
C#(使用代码转换器工具生成,我没有对其进行测试。)
public static double GetGrayScalePercentOfImage(Image img)
{
switch (img.PixelFormat)
{
case PixelFormat.Format16bppGrayScale:
return 100.0D;
default:
int pixelCount = (img.Width * img.Height);
int bytesPerPixel = (Image.GetPixelFormatSize(img.PixelFormat) / 8);
if ((bytesPerPixel != 3) && (bytesPerPixel != 4)) {
throw new NotImplementedException(message:"Only pixel formats that has 3 or 4 bytes-per-pixel are supported.");
} else {
List<double> GrayscalePercentList = new List<double>();
FrameDimension frameDimension = new FrameDimension(img.FrameDimensionsList[0]);
int frameCount = img.GetFrameCount(frameDimension);
long grayscalePixelCount = 0; // of current frame.
int tempVar = frameCount - 1;
for (int frameIndex = 0; frameIndex <= tempVar; frameIndex++) {
img.SelectActiveFrame(frameDimension, frameIndex);
// Lock the bitmap's bits.
Bitmap bmp = (Bitmap)img;
Rectangle rect = new Rectangle(Point.Empty, bmp.Size);
BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
// Get the address of the first line.
IntPtr ptr = data.Scan0;
// Declare an array to hold the bytes of the bitmap.
int numBytes = (data.Stride * bmp.Height);
byte[] rgbValues = new byte[numBytes];
// Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, numBytes);
// Unlock the bitmap's bits.
bmp.UnlockBits(data);
// Iterate the pixels.
for (int pixelIndex = 0; pixelIndex <= rgbValues.Length - bytesPerPixel; pixelIndex += bytesPerPixel) {
Color c = Color.FromArgb(red:rgbValues[pixelIndex + 2], green:rgbValues[pixelIndex + 1], blue:rgbValues[pixelIndex]);
if ((c.R == c.G) && (c.G == c.B) && (c.B == c.R)) {
grayscalePixelCount += 1;
}
}
double frameGrayscalePercent = ((grayscalePixelCount / (double)pixelCount) * 100);
GrayscalePercentList.Add(frameGrayscalePercent);
grayscalePixelCount = 0;
}
return (GrayscalePercentList.Sum() / frameCount);
}
}
}