VB.NET-Tipp 0092: Zahl der Farben einer Bitmap
von Danielo
Beschreibung
Das folgende Beispiel zeigt, wie die Anzahl der unterschiedlichen Farben in einem Bild ermittelt werden können.
Die Vorgehensweise, ein großes Array (rund 2MB) anzulegen, jeden Farbwert des Bildes als Index in diesem Array zu verwenden und dort ein Bit zu setzen, hat sich als die schnellste Methode erwiesen. In einem direkten Vergleich dieser VB.NET-Implementierung gegen eine Implementierung in Assembler des selben Codes war ASM nur etwa um den Faktor 2 schneller.
Schwierigkeitsgrad: | Framework-Version(en): .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5 | .NET-Version(en): Visual Basic 2005, Visual Basic 2008 | Download: |
' Dieser Quellcode stammt von http://www.activevb.de ' und kann frei verwendet werden. Für eventuelle Schäden ' wird nicht gehaftet. ' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. ' Ansonsten viel Spaß und Erfolg mit diesem Source! ' Projektversion: Visual Studio 2008 ' Option Strict: An ' Option Explicit: An ' Option Infer: An ' ' Referenzen: ' - System ' - System.Data ' - System.Deployment ' - System.Drawing ' - System.Windows.Forms ' - System.Xml ' - System.Core ' - System.Xml.Linq ' - System.Data.DataSetExtensions ' ' Imports: ' - System ' - System.Collections ' - System.Collections.Generic ' - System.Data ' - System.Drawing ' - System.Diagnostics ' - System.Windows.Forms ' - System.Linq ' - System.Xml.Linq ' ' ############################################################################## ' ################################# Form1.vb ################################### ' ############################################################################## Imports System.Runtime.InteropServices Public Class Form1 Private Sub Form1_Shown(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Shown Dim o As New IO.DirectoryInfo( _ System.Windows.Forms.Application.StartupPath) LoadNewPicture(o.Parent.Parent.FullName & "\P8301141.JPG") End Sub Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then LoadNewPicture(OpenFileDialog1.FileName) End If End Sub Private Sub LoadNewPicture(ByVal FullName As String) Dim bmp As New Bitmap(FullName) PictureBox1.Image = bmp Dim c As UInt32 = CountColors(bmp) MessageBox.Show("Das Bild enthält " & c & " unterschiedliche Farben.") End Sub Private Function CountColors(ByVal InBitmap As Bitmap) As UInt32 ' Um komfortabler durch die Bilddaten iterieren zu können, wird das Bild ' zuerst in 32Bit Farbtiefe konvertiert: Dim dwPixels(InBitmap.Height * InBitmap.Width - 1) As UInt32 Dim hPixels As GCHandle = GCHandle.Alloc(dwPixels, GCHandleType.Pinned) Dim bmp32Bpp As New Bitmap(InBitmap.Width, _ InBitmap.Height, InBitmap.Width * 4, _ Imaging.PixelFormat.Format32bppRgb, hPixels.AddrOfPinnedObject) Using gr As Graphics = Graphics.FromImage(bmp32Bpp) gr.DrawImageUnscaledAndClipped(InBitmap, New Rectangle(0, 0, _ bmp32Bpp.Width, bmp32Bpp.Height)) End Using ' Jetzt zählen: Dim dwTable(CInt(2 ^ 19) - 1) As Int32 Dim index As Int32 Dim bit As Int32 Dim cDifferentColors As UInt32 For i = 0 To dwPixels.Length - 1 ' das höchstwertige Byte ist unbenutzt und muss ausmaskiert werden: index = CInt(dwPixels(i) And &HFFFFFF) bit = 1 << (index And &H1F) index >>= 5 If (dwTable(index) And bit) = 0 Then cDifferentColors += 1UI dwTable(index) = dwTable(index) Or bit End If Next ' GC Handle freigeben: hPixels.Free() Return cDifferentColors End Function End Class
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.
Archivierte Nutzerkommentare
Klicken Sie diesen Text an, wenn Sie die 1 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.
Kommentar von Richard Bauer am 16.08.2011 um 15:31
Hallo -
ich bin wirklich begeistert von dieser schnellen funktion ...
und habe (vergeblich) versucht den "schlüssel" bei 32bit besser zu verstehen ...
oder anders gesagt; mit bitshiften noch neuling :-)
besteht die möglichkeit mir ein bisserl auf die sprünge zu helfen:
For i = 0 To dwPixels.Length - 1
' das höchstwertige Byte ist unbenutzt und muss ausmaskiert werden:
index = CInt(dwPixels(i) And &HFFFFFF)
' dwPixels(i) enthält doch die FARBE/nummer !?
' ist diese vom ARGB-format und wie könnte ich diese aus
' z.B: dwPixels(i) = 4294901760 zuordnen ?
'
bit = 1 << (index And &H1F)
' wird hier die ERSTE stelle (die 4) weggeshiftet
index >>= 5
' und hier um "A(rgb)" nach rechts ?
Dim test As Integer = CInt(dwPixels(i) >> 1)
If (dwTable(index) And bit) = 0 Then
cDifferentColors += 1UI
dwTable(index) = dwTable(index) Or bit
End If
Next
währe echt super mir da den "lehrlingseffekt" zukommen zu lassen *wedel*
danke