Programm sucht nach doppelten Fotos

    • Beta

    Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von DerHans117.

      Programm sucht nach doppelten Fotos

      Name des Programms:
      Das Programm, das ich euch jetzt gerne mal vorstellen möchte, heißt PhotoSearch. . Der Name stammt aus dem Englischen und lässt sich darauf schließen, dass es hier bei um ein Suchprogramm für Fotos, die einen unterschiedlichen Dateinamen aber doch das gleiche Bild sind, handelt.

      Beschreibung:
      Man gibt ein Foto, das in einem bestimmten Verzeichnis gesucht werden soll, als Originalbild an. (Der Begriff Originalbild ist im Moment nur eine Notlösung - wenn ihr Vorschläge für einen besseren Namen bzw. Begriff habt, immer her damit). Anschließend wählt man das Verzeichnis, in dem das Bild gesucht werden soll, aus.

      Zum Programm:
      Es werden jeweils 5 verschiedene Pixel, die auf dem Originalbild verteilt sind (Verteilung nach Benutzer), mit dem "Vergleichsbild" verglichen. Die Koordinaten bei dem Vergleichsbild sind die gleichen wie die vom Originalbild.

      Wird das Bild gefunden, so erscheint eine MessageBox mit dem Titel "Bild gefunden!" und die Suche wird abgebrochen; wird nichts gefunden, erscheint am Ende eine MessageBox mit der Beschriftung "Bild nicht gefunden!".


      Screenshot(s):
      Screenshot ist im Anhang.

      Verwendete Programmiersprache und IDE:
      Visual Basic .NET (IDE: VB 2010 Express)

      Systemanforderungen:
      .NET Framework 4.0

      Download:
      Weiter unten

      Lizenz/Weitergabe:
      Im Moment nur als Beta-Version. Ich möchte einfach mal wissen, wie eure Meinung dazu ist.


      PS: Da ich nur ein Hobbyprogrammierer bin und bis jetzt nur für programmiert habe, möchte ich gerne auch wissen, was ihr vom Code hält. Ich habe bislang keine Schulungen gemacht und habe mir sonst alles selber beigebracht, deshalb könnten da Fehler enthalten sein.
      Bilder
      • Programm_Vorschau_2.jpg

        109,83 kB, 863×474, 213 mal angesehen
      Dateien

      Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DerHans117“ ()

      Aber geht nicht zwangsläufig. Wenn das Bild zum Beispiel einmal als JPG und einmal als TIF gespeichert wurde, dann haben die unterschiedliche Hashes. Wegen den Fileheadern, die ja unterschiedlich sind.
      Und 5 Pixel eines Bildes zu prüfen dauert nicht mal einen Wimpernschlag, da braucht man wohl nicht mehr viel zu optimieren. (Da sollte selbst GetPixel() schnell genug sein, habs nicht getestet. Sonst mal LockBits anschauen bei Google)

      Skybird schrieb:

      Das sind ja Ubisoftmethoden hier !

      Habt ihr keine Kritik ?

      Ich meine die Ordnung von meinem Code bzw. die Struktur ist doch miserabel...

      Und ist das wirklich die einzigste Lösung, indem man das Bild zeichnen lässt und es dann per .GetPixel() abruft ?
      Irgendwie bin ich damit unzufrieden...
      Stimmt, ich kann dem Bitmap ein Bild zuordnen...Dann müsste das nicht gezeichnet werden..

      DerHans117 schrieb:

      Und ist das wirklich die einzigste Lösung, indem man das Bild zeichnen lässt und es dann per .GetPixel() abruft ?
      Irgendwie bin ich damit unzufrieden...
      Stimmt, ich kann dem Bitmap ein Bild zuordnen...Dann müsste das nicht gezeichnet werden..

      vb-checker schrieb:

      Sonst mal LockBits anschauen bei Google)

      ;)
      bobpowell.net/lockingbits.htm

      Skybird schrieb:

      Das sind ja Ubisoftmethoden hier !

      Achso ...

      bei unterschiedlichen Dateiformaten geht das wirklich nicht ...
      ich dachte dabei an den Fall wenn man wahrlos seine Dateien
      kopiert und verstreut ... :)
      Kenne nur zu viele Leute, die das so machen ... Bei jpeg und
      Tif kannst nat. auch wegen dem Farbraum, Qualität und Konverter
      pech haben dass er daneben liegt und keine treffer findet.
      Hier wäre es dann nach deiner Methodik besser das Bild auf die
      schlechteste Quali runterzuholen und dann zu vergleichen

      Interessant wäre auch das ARToolkit mit reinzubringen ...
      dann kannst du wirklich nach gleichen bildern suchen, die
      sich auch in Helligkeit, Kontrast ... unterscheiden ...

      Cool wäre auch noch die Punkte und den Pfad vom Bild zu
      Speichern, dann suchst du extrem schnell, vorausgesetzt du
      hast vorher alle Bilder einmal eingelesen ...

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Phreak87“ ()

      DerHans117 schrieb:

      Habt ihr keine Kritik ?

      och, so einiges.

      Zunächstmal scheinen dir die Klassen FileInfo und DirectoryInfo unbekannt zu sein, denn kein vernünftiger Mensch würde Strings in eine File-Listbox füllen - Keine Strings in die File-Listbox! (der Link enthält übrigens auch einen darauf aufgebauten PictureViewer, der für dich sehr interessant sein dürfte.)

      Dann gibts bei dir gar keine Trennung von Daten und Oberfläche, mit dem Ergebnis, dass du nicht die Files selbst durchgehst, sondern etwas ganz komisches mit der Listbox machst (nämlich eine Ereigniskette).

      sicher 100mal schneller wäre, du hättest eine List(Of FileInfo) und würdest diese durchgehen, bis Übereinstimmung gefunden.

      Ist natürlich hübsch mit der rumklappernden Picturebox, die da ständig refresht wird, aber auf diese Weise ist deine Suche die meiste Zeit damit beschäftigt, anzuzeigen, dass sie beschäftigt ist.


      Auch sehr abstrus ist, bei jeder Suche die Punkte-Konstellation aus einer Datei einzulesen, sogar aus 2 verschiedenen Dateien.
      Hier würde sich ein Eintrag in den Settings gut machen - gugge "SetSettings" auf Movie-Tuts und vlt. auch Settings richtig verwenden + binden.

      Was auch schlimm ist sind die vielen vielen KlassenMember in Form1.

      VB.NET-Quellcode

      1. Public Class Form1
      2. Dim Item As Object
      3. Dim OBild As Bitmap = New Bitmap(200, 200)
      4. Dim G As Graphics = Graphics.FromImage(OBild)
      5. Dim FBild As Bitmap = New Bitmap(200, 200)
      6. Dim GF As Graphics = Graphics.FromImage(FBild)
      7. Dim OBildOk As Boolean = False
      8. Dim SVerOk As Boolean = False
      9. Public Optionen As Integer = 0
      10. Dim Ausw As ToolStripMenuItem
      11. Dim Möglichkeit As Integer = 1
      12. Dim GebDatenLes As IO.StreamReader
      13. Dim WerteText As String
      14. Dim Zahlentext() As String
      15. Dim X As Integer
      16. Dim Y As Integer
      17. Dim Int As Integer
      18. Dim OCol As Color
      19. Dim Punkte As Integer = 0
      20. Dim FCol As Color
      Da muß viel stärker gekapselt werden, und viel mehr lokal deklariert, damit man innerhalb einer Methode gleich sieht, was da für Variablen genutzt werden und wo die herkommen.

      IMO als Klassenvariable braucht man nur die beiden Bitmaps, die Graphics und die anzuwendende Vergleichs-Variante


      Und die Benamung ist teilweise übel. Manches ist sinnvoll benamt:

      VB.NET-Quellcode

      1. BeendenToolStripMenuItem, AlsPNGLadenToolStripMenuItem, AlsJPGLadenToolStripMenuItem, AlsBMPLadenToolStripMenuItem, VerzeichnisAuswählenToolStripMenuItem

      Manches ist Namens-Schrott:

      VB.NET-Quellcode

      1. ToolStripMenuItem1, PunkteToolStripMenuItem1, PunkteToolStripMenuItem, AllePunkteToolStripMenuItem, PunkteToolStripMenuItem3, PunkteToolStripMenuItem2


      Warum gibts 2 PunkteToolStripMenuItem_Click - Methoden?

      Gut findich den Umgang mit den Dateisystem-Dialogen.

      Und auch, dass du mehrere Click-Handler auf dieselbe Methode leitest (Hierbei wäre klare Benamung natürlich besonders wichtig). Nur wie du den Select dann aufbaust, um die Item zu unterscheiden ist umständlich:

      VB.NET-Quellcode

      1. Private Sub PunkteToolStripMenuItem_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PunkteToolStripMenuItem1.Click, PunkteToolStripMenuItem.Click, AllePunkteToolStripMenuItem.Click
      2. Item = sender
      3. If Item.ToString = PunkteToolStripMenuItem.ToString Then
      4. Optionen = 1
      5. ElseIf Item.ToString = PunkteToolStripMenuItem1.ToString Then
      6. Optionen = 2
      7. End If
      8. Einstellungspunkte.Show()
      9. End Sub
      Das ginge auch

      VB.NET-Quellcode

      1. Private Sub PunkteMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PunkteToolStripMenuItem1.Click, PunkteToolStripMenuItem.Click, AllePunkteToolStripMenuItem.Click
      2. If sender Is PunkteToolStripMenuItem1 Then
      3. Optionen = 1
      4. ElseIf sender Is PunkteToolStripMenuItem1 Then
      5. Optionen = 2
      6. End If
      7. Einstellungspunkte.Show()
      8. End Sub
      9. 'oder
      10. Private Sub PunkteMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PunkteToolStripMenuItem1.Click, PunkteToolStripMenuItem.Click, AllePunkteToolStripMenuItem.Click
      11. Select Case True
      12. Case sender Is PunkteToolStripMenuItem1
      13. Optionen = 1
      14. Case sender Is PunkteToolStripMenuItem1
      15. Optionen = 2
      16. End Select
      17. Einstellungspunkte.Show()
      18. End Sub


      Und zuletzt findet dein Prog nur die erste Kopie des Originals - nicht alle weiteren Doubletten

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „ErfinderDesRades“ ()

      Vielen Dank für den Tipp mit dem DirectoryInfo und
      FileInfo…Die lästigen Strings haben mich eigentlich schon längst gestört, doch
      leider hatte ich in der Vergangenheit keine andere Wahl, da ich das andere halt
      nicht kannte.

      Ich mache es bewusst nicht mit einer List(Of FileInfo)
      auch wenn mir die Methode neu ist, da ich gerne will, dass der Benutzer sieht,
      dass nach seinem Bild gesucht wird.

      Die Ereigniskette bei der Listbox habe ich bewusst
      gewählt, da ich weniger Variablen haben wollte. Ich versuche immer mit so wenig
      Variablen wie möglich auszukommen. Aber die Ereigniskette werde ich jetzt wohl
      abschaffen und eine Schleife hinklatschen…

      Das Problem mit dem Variablen ist auch das ich meist
      nicht weiß ich wo ich die hin setzen soll, weil im Grunde genommen werden die
      in einer Sub, wenn man sie nochmal aufruft, neu gemacht, oder nicht ?

      Bei der Suche wird jeweils nur aus einer Datei Werte
      ausgelesen. Dabei hat man die Möglichkeit eine 5-Punkt- oder eine
      10-Punktsuchmethode auszuwählen.

      Die Settings sind mir bekannt, doch ich war etwas bequem
      und habe das alles in eine txt-Datei geschrieben
      Nach langer Überlegung bau' ich das Programm doch jetzt so um, dass es jetzt "smarter" ist. Die Pictureboxen werden abgeschafft, da sie durch die Schnelligkeit der Schleifen total überflüssig geworden ist.
      Ich weiß, dass es solche Programme schon existieren. Aber irgendwie hatte ich mal Interesse daran, sowas nach zu basteln ;)
      So, ich habe das Projekt nochmal überarbeitet...Schön und schick gemacht. Vorallem smart ;)

      Paar Variablen musste ich über die Subs schreiben, da es anders nicht ging.

      Hier zu hätte ich gern auch wieder Kritik!

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DerHans117“ ()

      viiiel besser, findich. Der Code ist nicht ein Viertel, von dem, was vorher einen verwirrte.
      Immer noch scherst du dich um korrekte Benamung keinen Deut - aber glaub mir: Es kostet keine 10 Sekunden, "Liste2" in "_BilderFiles" umzubenennen, und dann weiß man, dass da FileInfos drinne sind (keine Bilder), und der letzte Depp versteht dann die Bearbeitungsschritte.

      VB.NET-Quellcode

      1. For i As Integer = 0 To Anzahl2 - 1
      2. Dim FBild As Bitmap = New Bitmap(_BilderFiles.Item(i).FullName)
      3. For Punkte As Integer = 0 To 4
      4. Dim OColor As Color = FarbenListe(Punkte)
      5. Select Case Punkte
      6. Case 0
      7. Fcolor = FBild.GetPixel(20, 20)
      8. Case 1
      9. Fcolor = FBild.GetPixel(FBild.Width - 20, 20)
      10. Case 2
      11. Fcolor = FBild.GetPixel(20, FBild.Height - 20)
      12. Case 3
      13. Fcolor = FBild.GetPixel(FBild.Width - 20, FBild.Height - 20)
      14. Case 4
      15. Fcolor = FBild.GetPixel(CInt(FBild.Width / 2), CInt(FBild.Height / 2))
      16. End Select
      17. If OColor = Fcolor Then
      18. Chance += 1
      19. End If
      20. Next
      Na, gut, das versteht man immer noch nicht wirklich. ZB, was warum du über die .Item-Property gehst, statt direkt zu indizieren

      VB.NET-Quellcode

      1. Dim FBild As Bitmap = New Bitmap(_BilderFiles(i).FullName)
      Und was diese komische Variable Anzahl2 soll, weil eine List(Of T) weiß ihre Anzahl selbst

      VB.NET-Quellcode

      1. For i As Integer = 0 To _BilderFiles.Count - 1
      und überhaupt: warum du kein For Each nimmst

      VB.NET-Quellcode

      1. For Each fi As FileInfo in _BilderFiles
      2. dim FBild=new Bitmap(fi.Fullname)
      3. '...
      Da bräuchtest du keine Anzahl, und auch keinen Zähler mehr :)

      Du hast da übrigens einen guten Code, mit dem du aus einem Bild die Farbwerte an den Punkten berechnest und in eine Liste packst. Diesen Code kannst du mehrfach verwenden, indem du ihn in eine Methode auslagerst, und dann sowohl auf die Orig-Bitmap anwendest als auch jeweils auf die zu testende Bitmap. Dann hättest du 2 PunktFarben-Listen - sowas kann man mit 3 Zeilen gegeneinander abgleichen.
      Signatur-Vorschlag:

      VB.NET-Quellcode

      1. Private Function GetPointColors (bmp as bitmap) as List(Of Color)
      2. '...

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

      Okay, du hattest recht. Ich sehe wohl den Wald vor voller Bäumen nicht. Das ist ja nett mit der Function, das Problem ist, ich habe noch nie eine geschrieben :( Ich werde mich dann mal im Internet schlau machen ;)

      Habe jetzt alles so hinbekommen...Nur das Problem ist, der erkennt die Liste nicht, in dem die gleichen Werte sind.

      VB.NET-Quellcode

      1. Public Class Bearbeitung
      2. Dim BilderInfosBe As List(Of IO.FileInfo) = Startform.Bilderliste
      3. Private Sub Bearbeitung_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      4. BackgroundWorker1.RunWorkerAsync(Startform.BildInfo.FullName)
      5. ProgressBar1.Minimum = 0
      6. ProgressBar1.Maximum = BilderInfosBe.Count - 1
      7. BackgroundWorker1.WorkerReportsProgress = True
      8. BackgroundWorker1.WorkerSupportsCancellation = True
      9. End Sub
      10. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      11. BackgroundWorker1.CancelAsync()
      12. Me.Close()
      13. End Sub
      14. Private Function FarbenHolen(ByVal Bild As Bitmap) As List(Of Color)
      15. Dim Farbenliste As List(Of Color) = New List(Of Color)
      16. Farbenliste.Add(Bild.GetPixel(20, 10))
      17. Farbenliste.Add(Bild.GetPixel(Bild.Width - 20, 20))
      18. Farbenliste.Add(Bild.GetPixel(20, Bild.Height - 20))
      19. Farbenliste.Add(Bild.GetPixel(Bild.Width - 20, Bild.Height - 20))
      20. Farbenliste.Add(Bild.GetPixel(CInt(Bild.Width / 2), CInt(Bild.Height / 2)))
      21. Return Farbenliste
      22. End Function
      23. Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
      24. Dim OBild As Bitmap = New Bitmap(Image.FromFile(e.Argument.ToString))
      25. Dim FarbeOriginal As List(Of Color) = New List(Of Color)
      26. FarbeOriginal = FarbenHolen(OBild)
      27. Dim FarbeFragezeichen As List(Of Color) = New List(Of Color)
      28. For Each BildInfo As IO.FileInfo In BilderInfosBe
      29. Dim Chance As Integer
      30. Dim FBild As Bitmap = New Bitmap(BildInfo.FullName)
      31. FarbeFragezeichen = FarbenHolen(FBild)
      32. For i As Integer = 0 To 4
      33. If FarbeFragezeichen(i) = FarbeOriginal(i) Then
      34. Chance += 1
      35. End If
      36. Next
      37. If Chance = 5 Then
      38. Dim Abfrage As String = MsgBox("Bild gefunden!" & vbCrLf & "Explorer öffnen ?" & vbCrLf & BildInfo.FullName, MsgBoxStyle.YesNo, "PhotoSearch.").ToString
      39. If Abfrage = "Yes" Then
      40. Process.Start("explorer", BildInfo.FullName)
      41. End If
      42. Exit Sub
      43. End If
      44. BackgroundWorker1.ReportProgress(BilderInfosBe.IndexOf(BildInfo))
      45. Next
      46. MsgBox("Es wurde kein entsprechendes Bild gefunden!")
      47. End Sub
      48. Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
      49. ProgressBar1.Value = e.ProgressPercentage
      50. End Sub
      51. Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
      52. Me.Close()
      53. End Sub
      54. End Class

      Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von „DerHans117“ ()

      bitte stell den Code nochmal lesbar ein (kannst ja deinen Post editieren): Bitte VB-Tag benutzen - aber richtig (es kommt auf die Einrückungen an).
      Und entferne dabei gleich die üflüssigen Leerzeilen.

      Dieser Vergleich ist natürlich unsinn

      VB.NET-Quellcode

      1. If FarbeFragezeichen Is FarbeOriginal Then BackgroundWorker1.CancelAsync()
      Du willst ja nicht die Identität der Listen-Objekte vergleichen, sondern die Gleichheit jedes der darin enthaltenen Punkte.
      Also eine For i - Schleife musste schon noch investieren.

      Und was soll BackgroundWorker1.CancelAsync()?
      Im Falle dass Gleichheit aller Punkte gefunden wurde kommts nur drauf an, dass darüber Meldung gemacht wird, und die Methode verlassen wird.
      Geschieht bei dir auch, aber über die Umständlichkeit, dass erst per .CancelAsync das CancellationFlag gesetzt wird, welches dann zwei Zeilen weiter abgefragt wird, und zum Methoden-Ausstieg führt.
      Wie gesagt: unverständlich kompliziert, denn du kannst direkt aussteigen, ohne das Gefummel mittm Cancelation-Zeugs.
      Ich hoffe das ist jetzt so okay wie ich den Code gepostet habe. ;)

      Irgendwie habe ich mir das schon gedacht, aber du meintest, man benötige dafür nur 3 Zeilen Code. Vielleicht habe ich das Ganze auch falsch verstanden. Das mit der Methode/Function hatte ich auch zuerst falsch verstanden und dann nach hinein ausgebessert.

      Naja, mein du nicht, dass es sauberer aussieht, wenn man den BackgroundWorker1.CancelAsync() rein baut ? Ich meine, der wurde ja nicht umsonst entwickelt ;)

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DerHans117“ ()

      DerHans117 schrieb:

      Ich hoffe das ist jetzt so okay wie ich den Code gepostet habe. ;)

      Nein.
      also mich frustriert das. Dir muß doch auffallen, dass die geposteten Einrückungen anners sind als wie sie sich im VisualStudio darstellen?
      ich hätte eiglich gedacht, meine Anleitung Bitte VB-Tag benutzen - aber richtig sei idiotensicher, und da steht doch auch, dass man den Code neu aus dem VS-Editor nehmen muß und einpasten - ich mein: stört euch das nicht selber, wenn die Code-Struktur durch falsche Einrückungen kaum noch zu erfassen ist?
      jo, sieht doch gut aus. Nur sind halt noch die unnötigen Leerzeilen innerhalb der Methoden drin - die erschweren etwas die Orientierung, wo eine Methode anfängt / aufhört.

      und

      VB.NET-Quellcode

      1. Dim Abfrage As String = MsgBox("Bild gefunden!" & vbCrLf & "Explorer öffnen ?" & vbCrLf & BildInfo.FullName, MsgBoxStyle.YesNo, "PhotoSearch.").ToString
      ist ein Fall von ToString überall anhängen

      Weil was die Msgbox zurückgibt ist unverändert zur Bestimmung der User-Eingabe viel besser geeignet, als wenns erst nach String gedreht wird.
      Wunderbar ;) Danke dir, jetzt ist mein Wissen wieder erweitert ;)
      Das mit .ToString() hatte ich mal auf einer anderen Seite vor einem Jahr entdeckt...seit dem habe ich das immer so gemacht, aber das es auch anders geht, darauf wäre ich mal wieder nicht gekommen ;)

      VB.NET-Quellcode

      1. Public Class Bearbeitung
      2. Dim BilderInfosBe As List(Of IO.FileInfo) = Startform.Bilderliste
      3. Private Sub Bearbeitung_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      4. BackgroundWorker1.RunWorkerAsync(Startform.BildInfo.FullName)
      5. ProgressBar1.Minimum = 0
      6. ProgressBar1.Maximum = BilderInfosBe.Count - 1
      7. BackgroundWorker1.WorkerReportsProgress = True
      8. BackgroundWorker1.WorkerSupportsCancellation = True
      9. End Sub
      10. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      11. BackgroundWorker1.CancelAsync()
      12. Me.Close()
      13. End Sub
      14. Private Function FarbenHolen(ByVal Bild As Bitmap) As List(Of Color)
      15. Dim Farbenliste As List(Of Color) = New List(Of Color)
      16. Farbenliste.Add(Bild.GetPixel(20, 10))
      17. Farbenliste.Add(Bild.GetPixel(Bild.Width - 20, 20))
      18. Farbenliste.Add(Bild.GetPixel(20, Bild.Height - 20))
      19. Farbenliste.Add(Bild.GetPixel(Bild.Width - 20, Bild.Height - 20))
      20. Farbenliste.Add(Bild.GetPixel(CInt(Bild.Width / 2), CInt(Bild.Height / 2)))
      21. Return Farbenliste
      22. End Function
      23. Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
      24. Dim OBild As Bitmap = New Bitmap(Image.FromFile(e.Argument.ToString))
      25. Dim FarbeOriginal As List(Of Color) = New List(Of Color)
      26. FarbeOriginal = FarbenHolen(OBild)
      27. Dim FarbeFragezeichen As List(Of Color) = New List(Of Color)
      28. For Each BildInfo As IO.FileInfo In BilderInfosBe
      29. Dim Chance As Integer
      30. Dim FBild As Bitmap = New Bitmap(BildInfo.FullName)
      31. FarbeFragezeichen = FarbenHolen(FBild)
      32. For i As Integer = 0 To 4
      33. If FarbeFragezeichen(i) = FarbeOriginal(i) Then
      34. Chance += 1
      35. End If
      36. Next
      37. If Chance = 5 Then
      38. If MsgBoxResult.Yes = MsgBox("Bild gefunden!" & vbCrLf & "Explorer öffnen ?" & vbCrLf & BildInfo.FullName, MsgBoxStyle.YesNo, "PhotoSearch.") Then
      39. Process.Start("explorer", BildInfo.FullName)
      40. End If
      41. Exit Sub
      42. End If
      43. BackgroundWorker1.ReportProgress(BilderInfosBe.IndexOf(BildInfo))
      44. Next
      45. MsgBox("Es wurde kein entsprechendes Bild gefunden!")
      46. End Sub
      47. Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
      48. ProgressBar1.Value = e.ProgressPercentage
      49. End Sub
      50. Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
      51. Me.Close()
      52. End Sub
      53. End Class
      hab den Such-Algo noch bisserl gepimpt:

      VB.NET-Quellcode

      1. Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
      2. Dim OBild = New Bitmap(Image.FromFile(e.Argument.ToString))
      3. Dim FarbeOriginal = FarbenHolen(OBild)
      4. For Each BildInfo As IO.FileInfo In BilderInfosBe
      5. Dim FBild = New Bitmap(BildInfo.FullName)
      6. Dim FarbeFragezeichen = FarbenHolen(FBild)
      7. Dim i As Integer ' i ausserhalb der Schleife deklarieren
      8. For i = 0 To FarbeFragezeichen.Count - 1
      9. If FarbeFragezeichen(i) <> FarbeOriginal(i) Then Exit For 'abbruch: i erreicht nicht den maximal-wert
      10. Next
      11. If i = FarbeFragezeichen.Count Then 'nur nach vollständigem Durchlauf der For-Schleife ist i um 1 höher als der im For-Kopf angegebene "To"-Wert.
      12. If MsgBoxResult.Yes = MsgBox("Bild gefunden!" & vbCrLf & "Explorer öffnen ?" & vbCrLf & BildInfo.FullName, MsgBoxStyle.YesNo, "PhotoSearch.") Then
      13. Process.Start("explorer", BildInfo.FullName)
      14. End If
      15. Exit Sub
      16. End If
      17. BackgroundWorker1.ReportProgress(BilderInfosBe.IndexOf(BildInfo))
      18. Next
      19. MsgBox("Es wurde kein entsprechendes Bild gefunden!")
      20. End Sub
      • lokal deklarierte Variablen müssen nicht mit "As Type" spezifiziert werden - den Typ erkennt der Compiler selber
      • deklariere variablen genau, wo du sie brauchst - möglichst wenig weiter oben.
      • die Suchschleife ist nun flexibel - sie geht bis FarbeFragezeichen.Count-1. Es ist nun also problemlos möglich, in Farbeholen() die Anzahl der zu checkenden punkte abzuändern, ohne dass die Suchschleife deswegen failen würde.
      • beachte den Trick mit dem Zähler i, und wie der endgültige Zählerstand zur Entscheidung über die Bild-Identität genutzt werden kann.
      Oh je, langsam wird mir das zu kompliziert. Ich verstehe bei den letzten Post nur Bahnhof...
      Warum i = FarbeFragezeichen.Count ? Er läuft doch nur bis zum FarbeFragezeichen.Count - 1 ?

      VB.NET-Quellcode

      1. For i = 0 To FarbeFragezeichen.Count - 1
      2. If FarbeFragezeichen(i) <> FarbeOriginal(i) Then Exit For 'abbruch: i erreicht nicht den maximal-wert
      3. Next
      4. If i = FarbeFragezeichen.Count Then 'nur nach vollständigem Durchlauf der For-Schleife ist i um 1 höher als der im For-Kopf angegebene "To"-Wert.
      5. If MsgBoxResult.Yes = MsgBox("Bild gefunden!" & vbCrLf & "Explorer öffnen ?" & vbCrLf & BildInfo.FullName, MsgBoxStyle.YesNo, "PhotoSearch.") Then
      6. Process.Start("explorer", BildInfo.FullName)
      7. End If
      8. Exit Sub
      9. End If


      Was meist du genau damit ?
      "lokal deklarierte Variablen müssen nicht mit "As Type" spezifiziert werden - den Typ erkennt der Compiler selber"


      Bezieht sich das auf das, was ganz Anfang in diesem Post steht ?
      beachte den Trick mit dem Zähler i, und wie der endgültige Zählerstand zur Entscheidung über die Bild-Identität genutzt werden kann.


      Und warum den <>-Operator verwenden ? Es muss doch gleich sein und nicht ungleich...

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DerHans117“ ()

      DerHans117 schrieb:

      Warum i = FarbeFragezeichen.Count ? Er läuft doch nur bis zum FarbeFragezeichen.Count - 1 ?
      so funzt halt die For-Schleife: i zählt hoch, und's geht bis einschließlich FarbeFragezeichen.Count - 1 in den For - Körper hinein.
      Dann zählt es noch einen höher, stellt fest, dasses über dem Limit ist, und geht nicht mehr in den For-Körper hinein. Jo - welchen Wert hat i in dem Moment?
      Genau: 1 über dem Limit, und das Limit war FarbeFragezeichen.Count - 1, also hinter der For-Schleife steht i auf FarbeFragezeichen.Count, aber nur, wenn's For nicht abgebrochen wurde.

      lokal deklarierte Variablen müssen nicht mit "As Type" spezifiziert werden - den Typ erkennt der Compiler selber
      vergleiche einfach deinen Code mit meinem:

      VB.NET-Quellcode

      1. 'vgl
      2. Dim OBild As Bitmap = New Bitmap(Image.FromFile(e.Argument.ToString))
      3. 'mit
      4. Dim OBild = New Bitmap(Image.FromFile(e.Argument.ToString)) 'der Compiler "sieht", dass OBild eine Bitmap ist, das muß man ihm nicht sagen
      5. 'vgl auch
      6. Dim FarbeFragezeichen As List(Of Color) = New List(Of Color)
      7. '...
      8. '...
      9. '...
      10. '...
      11. FarbeFragezeichen = FarbenHolen(FBild)
      12. 'mit
      13. Dim FarbeFragezeichen = FarbenHolen(FBild) 'der Compiler "sieht", dass FarbeFragezeichen eine List(Of Color) ist - muß man ihm nicht sagen
      14. ' (v.a. muß man das nicht ganz woanders deklarieren)



      nochmal der Trick mit Zähler i:

      VB.NET-Quellcode

      1. Dim i As Integer ' i ausserhalb der Schleife deklarieren
      2. For i = 0 To FarbeFragezeichen.Count - 1
      3. If FarbeFragezeichen(i) <> FarbeOriginal(i) Then Exit For 'abbruch: i erreicht nicht den maximal-wert
      4. Next
      5. If i = FarbeFragezeichen.Count Then 'nur nach vollständigem Durchlauf der For-Schleife ist i um 1 höher als der im For-Kopf angegebene "To"-Wert.
      im Grunde ist die Kommentation üflüssig, wenn man vb "kann". Und ich kann den Kommentaren nix neues hinzufügen.
      Es ist doch klar ersichtlich, dass die For-Schleife abgebrochen wird, wenn 2 Punkte drankommen, die ungleich sind '<>'.
      Das 2 Punkte ungleich sind, ist doch das sichere Indiz, dass die Bilder ungleich sind - weitere Punkte müssen nicht getestet werden.

      Ja, und im weiteren ergibt sich ja auch in diesem Fall, dass i nicht seinen Maximal-Wert erreicht, und anhand dessen wird entschieden, dass die Bilder ungleich sind.
      (Gecodet ist natürlich der logische Umkehrschluss: Nur wenn i seinen Maximalwert erreicht, sind die Bilder gleich, und die msgbox kommt und pipapo.)