AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
Thema durchsuchen
Ansicht
Themen-Optionen

Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

Ein Thema von Harry Stahl · begonnen am 21. Feb 2016 · letzter Beitrag vom 28. Feb 2016
Antwort Antwort
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.731 Beiträge
 
Delphi 12 Athens
 
#1

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

  Alt 25. Feb 2016, 08:37
Meine CPU ist schon etwas älter, aber durchaus schnell genug für meine Zwecke:
...benötigt die Routine hier auf meinem Rechner ca. 80 MS um das ganze Bitmap zu prüfen, was ziemlich viel Zeit ist.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Memnarch
Memnarch

Registriert seit: 24. Sep 2010
737 Beiträge
 
#2

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

  Alt 25. Feb 2016, 09:48
Ach sach ma:
Wie misst du eigentlich die Zeit? Doch hoffentlich nicht mit Now()

Nochmal genauer gemessen:
Meine alte Variante brauchte ~ 5.8ms
Nen bisschen was umgestellt und jetzt läuft sie bei mir zwischen 3.9 - 4.1ms
(Vielleicht ist nen off by one error drin nicht genau geprüft *hust*)
Delphi-Quellcode:

type
  TRGBA = packed record
    B, G, R, A: Byte;
  end;

  PRGBA = ^TRGBA;

  TRGBA4 = array[0..3] of TRGBA;
  PRGBA4 = ^TRGBA4;

  TScanLine = array[0..100000] of TRGBA;
  PScanLine = ^TScanLine;

function HasTransparentRGBAValues(const bm:TBitmap): Boolean;
var
  z: Integer;
  RGBA: PScanLine;
  LPixels, LLastPixels: PRGBA4;
  LPixel: PRGBA;
  i: Integer;
begin
  RGBA := bm.Scanline[bm.Height-1];
  z := bm.Width * bm.Height;
  LPixels := @RGBA[0];
  LLastPixels := @RGBA[z div 4 * 4];
  while (LPixels <> LLastPixels) and ((LPixels[0].A and LPixels[1].A and LPixels[2].A and LPixels[3].A) = 255) do
    Inc(LPixels);
  Result := ((LPixels[0].A and LPixels[1].A and LPixels[2].A and LPixels[3].A) <> 255);
  if not Result then
  begin
    Inc(LPixels);
    LPixel := PRGBA(LPixels);
    for i := 0 to z mod 4 - 1 do
    begin
      if LPixel.A < 255 then
        Exit(True);
      Inc(LPixel);
    end;
  end;
end;
Da man Trunc nicht auf einen Integer anwenden kann, muss dieser zuerst in eine Float kopiert werden

Geändert von Memnarch (25. Feb 2016 um 10:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.561 Beiträge
 
Delphi 12 Athens
 
#3

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

  Alt 25. Feb 2016, 17:24
Ach sach ma:
Wie misst du eigentlich die Zeit? Doch hoffentlich nicht mit Now()

Nochmal genauer gemessen:
Messe mit

QueryPerformanceFrequency(iTimerFreq);
QueryPerformanceCounter(iTimerStart);

Das sollte doch OK sein, oder?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

  Alt 25. Feb 2016, 17:40
Gemütlicher geht das mit Delphi-Referenz durchsuchenTStopWatch
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.561 Beiträge
 
Delphi 12 Athens
 
#5

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

  Alt 25. Feb 2016, 18:29
Gemütlicher geht das mit Delphi-Referenz durchsuchenTStopWatch
Klar, das kannte ich auch schon, denn wenn man unter FMX was messen will (insbesondere andere OS), dann ist es da die angesagte Funktion.

Unter Windows benutzt TStopwatch aber auch QueryPerformanceCounter und hier hatte ich mir schon vor langer Zeit mal die benötigten MS-Funktionen in eigene Start- und Stop-Funktionen gekapselt.

Aber wer das noch nicht gemacht hat, kann hier Dank der neueren Delphi-Versionen direkt bequem per Einbindung der Systems.Diagnostics drauf zugreifen.
  Mit Zitat antworten Zitat
Amateurprofi

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

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

  Alt 25. Feb 2016, 19:15
Zu #54 von Memnarch:
Ich hätte da noch eine super superschnelle Funktion anzubieten, sehr kurz, unkompliziert und übersichtlich:

Delphi-Quellcode:
function HasTransparentRGBAValues(const bm:TBitmap): Boolean;
begin
   Result:=True;
end;
@Memnarch:
Ist natürlich nicht ernst gemeint, deshalb bitte nicht böse sein.
Aber genau das liefert Deine in #54 gepostete Funktion.
Ich habe mal versucht, zu verstehen was Deine Funktion genau macht und habe eine kommentierte Version erstellt.
Hoffentlich hab ich mich da nicht vertan.
Delphi-Quellcode:
function HasTransparentRGBAValues(bmp:TBitmap): Boolean;
type
   TRGBA = packed record
     B, G, R, A: Byte;
   end;
   PRGBA = ^TRGBA;
   TRGBA4 = array[0..3] of TRGBA;
   PRGBA4 = ^TRGBA4;
   TScanLine = array[0..100000] of TRGBA;
   PScanLine = ^TScanLine;
var
   z: Integer;
   RGBA: PScanLine;
   LPixels, LLastPixels: PRGBA4;
   LPixel: PRGBA;
   i: Integer;
begin
   RGBA := bmp.Scanline[bmp.Height-1]; // Zeigt auf erstes Pixel der Bitmap
   z := bmp.Width * bmp.Height; // Anzahl Pixel
   LPixels := @RGBA[0]; // Adresse des ersten Pixels
   LLastPixels := @RGBA[z div 4 * 4]; // Zeigt hinter das letzte durch 4 teilbare Pixel
   while (LPixels <> LLastPixels) and ((LPixels[0].A and LPixels[1].A and LPixels[2].A and LPixels[3].A) = 255) do
     Inc(LPixels);
   // LPixels zeigt jetzt
   // 1) entweder auf das erste von 4 Pixeln, von denen mindestens eins transparent ist.
   // 2) oder, wenn Z nicht durch 4 teilbar ist, hinter das letzte durch 4 teilbare Pixel.
   // 3) oder, wenn Z durch 4 teilbar ist, hinter das letzte Pixel der Bitmap.
   Result := ((LPixels[0].A and LPixels[1].A and LPixels[2].A and LPixels[3].A) <> 255);
   // Die obige Ermittlung des Resultats ist für die Fälle 2 und 3 fehlerhaft
   // weil hier auf Speicherbereiche zugegriffen wird, die nicht mehr zur
   // Bitmap gehören.
   // Im Fall (2), weil ab LPixels maximal 3 Pixel folgen
   // Im Fall (3), weil LPixels bereits außerhalb der Bitmap liegt
   // Wenn in diesem Bereich mit undefiniertem Inhalt NICHT zufällig das 4te und
   // 8te und 12te und 16te Byte = 255 sind (was in der Regel nicht vorkommt),
   // wird als ergebnis TRUE geliefert.
   if not Result then
   begin
     Inc(LPixels);
     LPixel := PRGBA(LPixels);
     for i := 0 to z mod 4 - 1 do
     begin
       if LPixel.A < 255 then
         Exit(True);
       Inc(LPixel);
     end;
   end;
end;
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 Memnarch
Memnarch

Registriert seit: 24. Sep 2010
737 Beiträge
 
#7

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

  Alt 25. Feb 2016, 23:52
Bin nicht böse, hatte ja erwähnt ich könnte nen off by one haben
Da man Trunc nicht auf einen Integer anwenden kann, muss dieser zuerst in eine Float kopiert werden
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.561 Beiträge
 
Delphi 12 Athens
 
#8

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

  Alt 25. Feb 2016, 17:21
Meine CPU ist schon etwas älter, aber durchaus schnell genug für meine Zwecke:
...benötigt die Routine hier auf meinem Rechner ca. 80 MS um das ganze Bitmap zu prüfen, was ziemlich viel Zeit ist.
Also die erste Messung meiner Standard-Methode war im Debug-Modus mit AQTime, da habe ich wohl mal 80 MS gemessen. Das scheint aber relativ zu schwanken, jetzt kriege ich DEBUG-Modus immer um die 60 MS. Im Release-Modus um die 50 MS.

Im Unterschied dazu sind die Messungen mit der Demo-Anwendung, die ich geschrieben und hier ja mal hochgeladen hatte etwas anders.

Im Debug-Modus erhalte ich dort ca. 50 MS und im Release-Modus ca.23 MS.

Warum hier diese Abweichungen in der Messung zwischen AQTime und Queryperformancecounter sind, weiß ich leider auch nicht.
  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 15:49 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