Einzelnen Beitrag anzeigen

Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#45

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln

  Alt 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
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat