AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Thema durchsuchen
Ansicht
Themen-Optionen

Durchschnittsfarbe eines Bitmap "schnell" ermitteln

Ein Thema von KodeZwerg · begonnen am 10. Mai 2021 · letzter Beitrag vom 12. Mai 2021
Antwort Antwort
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#1

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln

  Alt 11. Mai 2021, 21:13
@KodeZwerg:

Die Methode, das Bild auf 1x1 Pixel zu reduzieren, liefert eine andere Durchschnittsfarbe.

Ich nehme auch an, dass GDI+ beim Skalieren auf 1x1 nicht oft die gleiche Durchschnittsfarbe berechnet. Du könntest ja auch auf ein 10x10 oder ähnlich skalieren und dort rechnen.

Die 1x1 Bitmap Farbe hängt natürlich u.a. vom verwendeten Skalier-Algorithmus ab.

Bliebe die Frage: Welche Farbe ein Mensch als die "bessere" Durchschnittsfarbe bewerten würde.

Hast du irgendwo einen Link auf wissenschaftliche Literatur (wäre interessant), wo sowas wie eine "Durchschnittsfarbe" besprochen wird. Ich nehme an, dass in der Grafikbranche nicht einfach über RGB addiert und der Mittelwert genommen wird. Da werden doch sicher andere Modelle "bemüht"?
Nein, ich hab darüber keine Literatur.
In einem anderen Projekt habe ich auch mal Durchschnittswerte gebildet, indem ich jedes Pixel in HSB umgerechnet, und die AvgWerte für H, S, B ermittelt und anschließend die Avg-HSB Werte wieder in RGB umgerechnet habe.
Egal wie ich die Avg-Werte errechnet habe, irgendwie wirkte die Avg-Farbe immer, wie soll ich es ausdrücken, "schmutzig". Aber vielleicht ist das einfach so bei einer Durchschnittsfarbe.
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

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

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln

  Alt 11. Mai 2021, 22:33
@Michael II: Ich habe eine mini Erklärung hier gefunden, aber verstehe den Inhalt nicht so ganz. Da geht es um die Farbannäherung zweier Pixel.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

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

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln

  Alt 11. Mai 2021, 22: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
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#4

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln

  Alt 12. Mai 2021, 10:18
Hier habe ich noch einen Code gefunden, aber wie es ausschaut machen die den gleichen Ansatz:
Ja, außer dass die vor dem eigentlichen "Zählen" die Daten aus der Bitmap in ein Array kopieren.
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

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

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln

  Alt 12. Mai 2021, 15:22
Danke skybibo und Amateurprofi ich werde es nach her mal durch-testen!

So werde ich vorgehen, hoffentlich ist das soweit okay, habe es selbst noch nicht getestet da ich gerade bemüht bin dutzende von methoden aus einer vcl-haupt-unit in eine seperate unit auszulagern.

Hier mein Code der vor Eurem geschaltet wird:
Delphi-Quellcode:
function FilenameToBmp(const AFilename: string; out ABmp: TBitmap): Boolean;
var
  wic: TWICImage;
begin
  if ((not FileExists(AFilename)) or (nil = ABmp)) then
    Exit(false);
  wic := TWICImage.Create;
  try
    ABmp.Dormant;
    ABmp.FreeImage;
    ABmp.ReleaseHandle;
    wic.LoadFromFile(AFilename);
    ABmp.Assign(wic);
    ABmp.PixelFormat := pf24bit;
    Result := Assigned(ABmp);
  finally
    wic.Free;
  end;
end;
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.550 Beiträge
 
Delphi 12 Athens
 
#6

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln

  Alt 12. Mai 2021, 15:35
OUT?

VAR Ohne (bzw. CONST) !!!

Es kommt was rein, also ist mindestens es IN-OUT,
aber eigentlich geht auch garnichts raus,
denn die Instanz/Variable/Parameter ändert sich garnicht.

Nur der Inhalt der Instanz ändert sich, aber das hat mit dem Objektzeiger nichts zu tun.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

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

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln

  Alt 12. Mai 2021, 15:41
OUT?

VAR Ohne (bzw. CONST) !!!

Es kommt was rein, also ist mindestens es IN-OUT,
aber eigentlich geht auch garnichts raus,
denn die Instanz/Variable/Parameter ändert sich garnicht.

Nur der Inhalt der Instanz ändert sich, aber das hat mit dem Objektzeiger nichts zu tun.
Also function FilenameToBmp(const AFilename: string; const ABmp: TBitmap): Boolean; so?
Danke fürs Lesen und Fehler erkennen!
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:17 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz