Feedback

VB - Durschnittsfarbe eines Bildes ermitteln

Veröffentlicht von am 8/3/2008
(1 Bewertungen)
Errechnet aus verschiedenen Farbpunkten eines Bildes die Durchschnittliche Farbe. Mit Quality kann man die Anzahl der Punkte bestimmen die horizontal und vertikal abgerufen werden.

z.B.:

PictureBox1.BackColor = GetAverageColor(picturebox1.Image)
Private Function GetAverageColor(ByVal img As Bitmap, _
                                     Optional ByVal Quality As Integer = 10) As Color
        Dim cDots As New ArrayList
        Dim Red, Blue, Green As Integer
        Dim HoriPoints As Integer = Math.Floor(img.Width / Quality)
        Dim VertiPoints As Integer = Math.Floor(img.Height / Quality)
        Dim result As Color = Color.White
        Try
            For i = 1 To Quality
                Dim x = HoriPoints * i - 1
                For ypos = 1 To Quality
                    Dim y = VertiPoints * ypos - 1
                    cDots.Add(img.GetPixel(x, y))
                Next
            Next
            For Each c As Color In cDots
                Red += c.R
                Blue += c.B
                Green += c.G
            Next
            Dim aColor As Color = Color.FromArgb(Red / cDots.Count, _
                                                 Green / cDots.Count, _
                                                 Blue / cDots.Count)
            result = aColor
        Catch ex As Exception
            Return result
        End Try

        Return result
    End Function

5 Kommentare zum Snippet

O.G. schrieb am 7/1/2010:
Bitte haut micht nicht wie geht das in C#?
Eine Konvertierung vom Typ "System.Array" in "System.Drawing.Color" ist nicht möglich.

Ich bin erst vor 1 Woche auf C# umgestiegen ich hab vorher nur mit dem borland builder (C++) gearbeitet und da hab ich sowas nicht gebraucht??
Rainer Hilmer schrieb am 7/1/2010:
Was bringt dieser Try/Catch-Block? Welche spezifische Exception könnte dort auftreten?
1. Nur "Exception" im Catch ist keine gute Lösung. In der Praxis sollten spezifische Ecxeptions abgefangen werden, weil je nach Typ eine unterschiedliche Behandlung programmiert wird.

2. Ganz allgemein, also nicht nur auf dieses Snippet bezogen: Ich würde im Catch-Block nicht das Ergebnis zurück geben, weil es aller Wahrscheinlichkeit nach entweder falsch oder ganz unbrauchbar ist! Das würde dazu führen daß die Funktion(en) die das Ergebnis weiterverarbeiten dann ihrerseits mit einer Exception reagieren. Das wäre sogar noch der angenehmere Fall. Viel ungemütlicher wird es, wenn der Fehler gar nicht so offensichtlich zu Tage tritt! Eine falsche Durchschnittsfarbe bereitet keine großen Schmerzen. Ein falscher Buchungsbetrag dagegen kann einem Entwickler den Kopf kosten!
Keks1911 schrieb am 7/5/2010:
** Leider sieht man disese Sorte Try-Catch viel zu oft. Meine Vermutung ist, dass das einfach der alten Unsitte entspricht, den Handler-Code bei
On Error Resume Next
leer zu lassen. Es gibt zwei Lösungen: 1. Return in den Try-Block packen, im Catch löschen und dort eine Exception werfen. 2. Try/Catch komplett löschen. Private Funktionen sollten ohnehin nicht explizit werfen, sondern Fehler nach Möglichkeit innerhalb der Klasse behandeln.

** ByVal für ein Bitmap ist nicht sehr praktisch, da die Werte schnell sehr groß werden. Nimm ByRef.

** Das Snippet verletzt Option Strict. Wenn du statt ArrayList die generische Form List<Color> verwendest, funktioniert es auch in C# ohne Typecast (bei gleicher Performance).

Rainer Hilmer schrieb am 7/5/2010:
@Keks: Im Catch eine Exception werfen? Welchen Sinn soll das haben? Erst wird mit Try/Catch eine Exception abgefangen und dann doch wieder geworfen. Das kapier ich nicht.
Keks1911 schrieb am 8/5/2010:
@Rainer: auf diese Weise lässt sich eine aufgetretene Exception neu verpacken - in einen eigenen Typ, der einem mehr Informationen gibt als die DivideByZeroException die er hier erwartet. Ich erwarte, dass das Programm unbehandelte Ausnahmen an einer zentralen Stelle behandelt. Wenn hier jemand ein Bild mit Breite/Höhe 0 übergibt, dann sollte dieser Teil des Programms abbrechen und zurück zur Hauptroutine gehen. Damit man dabei keine Informationen verliert, baut man seine eigene Exception und packt eine Fehlerbeschreibung in den Text. Die ursprüngliche Exception kann man unter "InnerException" referenzieren.

Sinn und Unsinn, das für dieses Beispiel zu machen, ist natürlich streitbar.
 

Logge dich ein, um hier zu kommentieren!