Announcement

Collapse
No announcement yet.

Bitmaps bzw. Icons vergleichen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Bitmaps bzw. Icons vergleichen

    Hallo zusammen, ich versuche (inzwischen verzweifelt) zwei Bitmaps, bzw. eigentlich Icons) zu vergleichen. Hintergrund ist, das eine Dokumentenverwaltung (Dokumente und inzwischen eben auch Icons in einer Datenbank) zu den Dokumenten auch Icons anzeigen kann. Wird ein Dokument importiert, hole ich das Systemicon dazu und will prüfen, ob ich dieses Icon bereits in der DB habe, um nicht irgendwann einige Hunbdert(tausend?) mal z.B. das Word.doc Icon in der gleichen Tabelle zu haben, ich habe von Scanline bis Canvas.Pixel alles mögliche und unmögliche versucht, das Problem ist aber, das das gleiche Icon beim Vergleich eben nicht mehr gleich ist?! Zur Zeit aktuell ist folgende Prozedur (beim Experimentieren mit Scanline ist übrigends hier und da der Debugger ordentlich durcheinander gekommen), x1 und 2 sind ganz hilfreich um mittels überwachter Ausdrücke und wiederholungszähler 32 die jeweilige Zeile zu sehen. Lässt man das free mal weg und hinterher die bmps irgendwo aufs Formular pinnen sind sie optisch identisch!
    <pre>
    procedure Tdvmain.AddFile(filename:String);
    type TTest = TColor;
    var sysImg,myImg : Integer;
    icon : TIcon;
    fn : String;
    z1, z2 : PByteArray;
    x1, x2 : TTest;
    function iconsEqual:Boolean;
    var x, y : Integer;
    begin
    result := true;
    for y := 0 to bm1.height-1 do begin
    x1 := bm1.Canvas.Pixels[y,0]; //(bm1.ScanLine[y]^);
    x2 := bm2.Canvas.Pixels[y,0];//(bm2.ScanLine[y]^);
    z1 := bm1.ScanLine[y];
    z2 := bm2.ScanLine[y];
    for x := 0 to bm1.width-1 do begin
    if bm1.Canvas.Pixels[y,x] <> bm2.Canvas.Pixels[y,x] then begin
    //if abs(z1[x]-z2[x]) <> 0 then begin
    result := false;
    exit;
    end;
    end;
    end;
    end;
    begin
    icon := TIcon.Create;
    bm1 := Tbitmap.Create;
    bm2 := TBitmap.Create;
    try
    sysImg := GetShellImage(filename);
    sysIcons.GetIcon(sysImg,icon);
    Bm1.Height := Icon.Height; Bm1.Width := Icon.Width;
    Bm1.Canvas.Draw(0, 0, Icon);
    bm1.PixelFormat := pf24Bit;
    icons.First;
    myImg := -1;
    While not icons.Eof do begin
    testImg.Picture.icon.Assign(iconsIcon);
    application.ProcessMessages;
    bm2.Width := 0; bm2.Height := 0;
    bm2.FreeImage;
    application.ProcessMessages;
    bm2.Assign(bm1);
    bm2.Canvas.Draw(0, 0, testImg.Picture.icon);
    if iconsEqual then begin
    myImg := iconsId.AsInteger;
    break;
    end;
    icons.Next;
    end;
    ....
    finally
    icon.free; bm1.free; bm2.free;

    end;
    </pre>
    Kann jemand helfen?

  • #2
    Benutz doch eine Prüfsumme z.B. SH

    Comment


    • #3
      Warum verzichtest Du nicht einfach auf das Icon in der DB, und lässt dir mit SHGetFileInfo() immer das aktuell gültige Icon aus dem System geben ?

      gruß Hagen

      Achso, wenn ein Icon/Bitmap per XOR über ein anderes gezeichnet wird dann muß das Resultat ein vollständig schwarzez Icon/Bitmap ergeben wenn beide absolut identisch sind. Angenommen zwei bitmaps werden verglichen:

      <pre>

      Bitmap1.Canvas.CopyMode := cmSrcInvert;
      Bitmap1.Canvas.Draw(0, 0, Bitmap2);
      for Y := 0 to Bitmap1.Height -1 do
      for X := 0 to Bitmap1.Width -1 do
      if Bitmap1.Canvas.Pixels[X, Y] <> 0 then "nicht gleich"

      </pre>


      &#10

      Comment


      • #4
        Immer Systemicon geht nicht, weil die Benutzer das Icon wechseln können sollen, ich will nur beim einlesen eines neuen Dokumentes das Standardicon vergeben. Das vorherige Assign habe ich nur hinzugefügt, weil ich sonst ab dem zweiten icon, das verglichen wird reste der jeweils vorherigen icons im Hintergrund hatte, da musste der Vergleich also fehlschlagen...
        Und eine Prüfsumme kann ja auch nur sauber Funktionieren, wenn der vergleich an sich erstmal funktioniert!

        Comment


        • #5
          Moin Karsten,<br>
          <br>
          Wenn Du die Icons in der Form:<br>
          Pfad_zur_Datei_mit_dem_Icon,IconNummer<br>
          oder ähnlich speicherst, und aus diesen Informationen eine Tabelle machst, deren Index dann das einem Dokument zugeordnete Icon referenziert, kannst Du die Icons ganz leicht vergleichen, die Icons könnten Problemlos gewechselt werden, und zur Initalisierung könntest Du, ebenfalls recht problemlos, den Pfad zum Default Icon eines bestimmten Dateityps auslesen.<br>
          Würdest Du diese List jetzt beispielsweise in einer TStringList speichern, könnte das so aussehen, um einen Eintrag hinzuzufügen:<br>
          slIconList.AddObject('C:\WINNT\SYSTEM32\SHELL32.DL L\12',TObject(icDOC));
          Dem Dokument wäre dann als Icon icDOC zugeordnet (icXXX wäre eine Menge von entsprechenden Icon Indizes der verschiedenen Dateitypen), und könnte mit slIconList.IndexOfObject(TObject(icDOC)) ermittelt werden.<br>
          Durch das zusätzliche Objekt würde sich eine Änderung der Sortierfolge, bzw. das Löschen oder Einfügen eines Eintrages in der Liste nicht auf die den Dokumenten zugeordeten Icons auswirken.<br>
          Soll jetzt Dokumentenweise ein Icon zugeordnet werden können, könnte man als Objekt auch eine Dokumentennummer nehmen.<br>
          Selbst bei einem Eintrag je Dokument, wäre wohl auch der Platzbedarf geringer, mit dieser Methode geringer, als mit einem 16x16 Icon.<br>
          <br>
          Ciao<br>
          Chri

          Comment


          • #6
            Aber das ganze wäre Rechnerabhängig, es soll aber eine Mehrbenutzer(Mehrplatz)fähige Datenbankenwendung werden und bei mir ist Beispielsweise das Systemlaufwerk i und nicht c, das ist zwar zugegebener massen seleten, ich möchte aber (obwohl ich es für Sinvoll halte ) den Benutzern nicht vorschreiben keine Spielzeugwindowsversionen zu benutzen (win98 andere Pfade als NT/2K/XP). Ist es denn nicht halbwegs vernünftig möglich, icons zu vergleichen

            Comment


            • #7
              Moin Karsten,<br>
              <br>
              das mit dem festen Laufwerk war ja nur als Beispiel gedacht (bei mir wäre das Systemlaufwerk K<br>
              Es spricht natürlich nichts dagegen, beispielsweise die entsprechenden Umgebungsvariablen zu benutzen.<br>
              Einen Widerspruch sehe ich aber bei Deinem Vorhaben:<br>
              Soll das ganze Rechnerunabhängig laufen, kann ein User einem bestimmten Dokument kein spezielles Icon zuweisen, wenn diese Information dann nicht lokal oder Userspezifisch gespeichert wird.<br>
              Ausserdem:<br>
              Wenn die User selber Icons zuweisen können, wird ein User, der mal auf dem Rechner eines Kollegen sich etwas ansieht Verständnisprobleme haben, wenn er nicht die gewohnte Icons vorfindet. Stichwort: Ergonomie.<br>
              Um ein identisches Icon zu ermitteln, ist der Weg über eine Prüfsumme, wie Andreas es vorgeschlagen hat, wohl der einzig gangbare Weg. Es ist zwar möglich, dass optisch gleiche Icons einen unterschiedlichen Dateiaufbau haben, aber für sehr wahrscheinlich halte ich das nicht. Um auf anderem Wege zu prüfen, ob die Dateien gleich sind, müsstest Du wohl oder übel die Datei analysieren und auf ein ein bestimmtes, von Dir zu wählendes Format normalisieren, bevor Du dann auf Gleichheit prüfen kannst. Falls Du das Format nicht haben solltest: Bei www.wotsit.org sollte es das geben.<br>
              <br>
              Ciao<br>
              Chris<br>
              <br>
              PS: Vielleicht solltest du allerdings die Grösse und Farbtiefe vorschreiben, oder zumindest einschränken, sonst hast Du eventuell irgendwann mal so ziemlich alle Formate von 16x16x2 bis 64x64x32.<br&gt

              Comment


              • #8
                Hast Du meinen obigen Vorschlag probiert ? Dieser Weg vergleicht beide Bitmaps bzw. Icons direkt. Man kann nun vorher das Farbformat auf 24Bit ändern und somit unabhängig von der Bitmap/Icon Farbtiefe vergleichen.

                Gruß Hage

                Comment


                • #9
                  @Christian: Es soll ja nicht jeder Benutzer jeder Datei ein eigenes Icons zuweisen können, sondern das Icon soll für alle Benutzer gelten, es soll einfach nur eine Möglichkeit werden, optisch zwischen z.B. einer Urkunde und einer Mitteilung zu unterscheiden, auch wenn beides Worddokumente sind, eine Iconschlacht soll das nicht werden..

                  @Hagen Jups habe ich latürnich probiert und mich hate es ziemlich zur Verzweiflung gebracht, das ein und das selbe Icon, zweimal nacheinander eingelesen nicht als gleich erkannt wurden, auch wenn beide auf 24 Bit gestellt wurden. Inzischen habe ich festgestellt, das hier seltsame Dinge bei der Speicherung über Ado in eine Datenbank [iconsIcon.assign(img.Picture.icon)] geschehen. Es handelt sich zur Zeit um ein Feld des Typs "OLE-Objekt" einer Access Datenbank (was anderes gibts da irgendwie nicht) und betsimmte Icons haben nach dem Speichern und anschließendem verwenden aus der DB andere Farben als vorher?! Muss ich wohl nochmal hier im Forum suchen, ob ich dazu was finde.

                  Zur Zeit gehe ich den etwas umständlichen weg, beide Icons in einen Memory-Stream zu speichern und diese Beiden zu vergleichen, das klappt..

                  Comment


                  • #10
                    Wieso umständlich ? ist doch eine gute Idee. Nun könntest Du über beide MemoryStream's eine Prüfsumme berechnen und nur diese vergleichen.

                    Gruß Hage

                    Comment


                    • #11
                      Jups aber umständlich trotzdem, weils halt leichter wäre, direkt auf die Bitmap zuzugreifen, da man diese ja sowieso hat, warum die dann nicht identisch sind, habe ich auch immer noch nicht ganz verstanden..

                      Comment

                      Working...
                      X