Registriert seit: 1. Feb 2018
3.691 Beiträge
Delphi 11 Alexandria
|
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
11. Mai 2021, 23:42
Hier habe ich noch einen Code gefunden, aber wie es ausschaut machen die den gleichen Ansatz:
Delphi-Quellcode:
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Runtime.InteropServices
Public Class Form1
Private WithEvents pb As New PictureBox
Private WithEvents cb As New CheckBox
Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.Controls.Add(pb)
Me.Controls.Add(cb)
pb.Size = New Size(Me.ClientSize.Width - 50, Me.ClientSize.Height - 50)
pb.Location = New Point(25, 25)
pb.Anchor = AnchorStyles.Left Or AnchorStyles.Bottom Or AnchorStyles.Right Or AnchorStyles.Top
pb.SizeMode = PictureBoxSizeMode.StretchImage
pb.BackColor = Color.Gray
cb.Location = New Point(2, 2)
cb.Text = "Use Lockbits Technique"
cb.Checked = True
Me.Text = "click the picturebox"
Me.Size = New Size(640, 480)
Me.BackColor = SystemColors.Control
End Sub
Private Sub pb_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles pb.Click
Using ofd As New OpenFileDialog
ofd.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.MyPictures
ofd.Filter = "Image Files(*.Bmp;*.Jpg;*.Gif;*.Png)|*.Bmp;*.Jpg;*.Gif;*.Png|All files (*.*)|*.*"
ofd.Title = "Select a picture"
Dim result As DialogResult = ofd.ShowDialog
If result = Windows.Forms.DialogResult.OK Then
Dim bm As Bitmap
Try
bm = DirectCast(Bitmap.FromFile(ofd.FileName), Bitmap)
Catch ex As OutOfMemoryException
MessageBox.Show("Couldn't load that file")
Exit Sub
Catch ex As FileNotFoundException
MessageBox.Show("Couldn't find that file")
Exit Sub
End Try
pb.Image = bm
If cb.Checked Then
Me.BackColor = GetAverageColor1(bm)
Else
Me.BackColor = GetAverageColor2(bm)
End If
Me.Text = Me.BackColor.ToString
End If
End Using
End Sub
Private Function GetAverageColor1(ByVal bm As Bitmap) As Color
If bm.PixelFormat <> PixelFormat.Format24bppRgb Then
MessageBox.Show("Image was not 24bppRgb")
Return Color.Black
End If
Dim bounds As New Rectangle(0, 0, bm.Width, bm.Height)
Dim bmd As BitmapData = bm.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
' The stride is the width of 1 row of pixels in bytes. As 1 pixels requires 3 bytes of color
' information, you would think this would always be 3 * bm.Width - But it isn't. Each row of
' pixels is aligned so that it starts at a 4 byte boundary, this is done by padding rows with
' extra bytes if required. (might be 8 byte boundary on x64)
Dim stride As Integer = bmd.Stride
' An array to store the color information:
Dim pixels(bmd.Stride * bm.Height - 1) As Byte
' Copy it all out of the bitmap:
Marshal.Copy(bmd.Scan0, pixels, 0, pixels.Length)
bm.UnlockBits(bmd)
Dim totalR As UInteger
Dim totalG As UInteger
Dim totalB As UInteger
For y As Integer = 0 To bm.Height - 1
For x As Integer = 0 To bm.Width - 1
' Get the index of a pixel in the array.
' The index will be the number of bytes in all the rows above the pixel,
' which is (y * stride)
' plus the number of bytes in all the pixels to the left of it
' so add x*3:
Dim index As Integer = (y * stride) + (x * 3)
totalB += pixels(index)
totalG += pixels(index + 1)
totalR += pixels(index + 2)
Next
Next
' Average the components
Dim pixelCount As Integer = bm.Width * bm.Height
Dim averageR As Integer = CType(totalR \ pixelCount, Integer)
Dim averageG As Integer = CType(totalG \ pixelCount, Integer)
Dim averageB As Integer = CType(totalB \ pixelCount, Integer)
Return Color.FromArgb(averageR, averageG, averageB)
End Function
Private Function GetAverageColor2(ByVal bm As Bitmap) As Color
' Slower, but simpler, way.
Dim totalR As UInteger
Dim totalG As UInteger
Dim totalB As UInteger
For y As Integer = 0 To bm.Height - 1
For x As Integer = 0 To bm.Width - 1
totalR += bm.GetPixel(x, y).R
totalG += bm.GetPixel(x, y).G
totalB += bm.GetPixel(x, y).B
Next
Next
Dim pixelCount As Integer = bm.Width * bm.Height
Dim averageR As Integer = CType(totalR \ pixelCount, Integer)
Dim averageG As Integer = CType(totalG \ pixelCount, Integer)
Dim averageB As Integer = CType(totalB \ pixelCount, Integer)
Return Color.FromArgb(averageR, averageG, averageB)
End Function
Private Sub cb_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cb.CheckedChanged
pb.Image = Nothing
Me.BackColor = SystemColors.Control
End Sub
End Class
Quelle
|
|
Zitat
|