Laden...

Magnification API langsam

Erstellt von -Hades- vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.619 Views
-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren
Magnification API langsam

Hallo,

ich hatte in einem vorherigen Thema (siehe BitBlt dauert unter bestimmten Umständen (Aero?, Windows 8?) zu langsam) die schlechte Performance von Bitblt unter Windows 8 angesprochen. Das ist anscheinend durch den Window Desktop Manager zu begründen, da erst so etwas wie ein Schnappschuss erstellt werden muss um an die Pixeldaten zu kommen.
Die Lösung zu einer schnelleren Methode schien die Verwendung der Magnification API. Diese habe ich auch eingebaut und es sah zunächst auch sehr gut aus. Jetzt habe ich das aber mal genauer untersucht mittels Stopwatch und es zeigt sich, dass von "schnell" keine Rede mehr sein kann.

Selbst ein Rechteck von 1x1 Pixel aufzunehmen dauert mindestens immer 4ms und die Zeit geht hoch bis zu 20ms. Bei Bitblt unter Windows XP und darunter dauert das konstant 0ms (mit Stopwatch gemessen). Wenn man das ziemlich oft macht und z.B. Hautpartien in einem großen Bild finden will merkt man das deutlich, da die Verarbeitung dann von ca. einer halben Sekunde auf 15 - 20 Sekunden steigt...

Vielleicht habe ich abe auch irgendwo einen Fehler gemacht, daher erkläre ich kurz mein Vorgehen:

Ich habe die C++ Methoden für die Magnification-Routinen in einer DLL ausgelagert. Es gibt eine Routine, die ich im Vorfeld einmal aufrufe, welche das Host- und das Magnification-Window erstellt und MagInitialize() aufruft und die Transformationsmatrix anwendet. Zudem wird hier die Methode MagSetImageScalingCallback() aufgerufen, welche eine Callback-Methode registriert, in der ich die Pixeldaten abfange und in eine Bitmap umwandle (C# Seite).

Eine zweite Routine, welche ich immer dann aufrufe wenn ich ein Rechteck des Screens lesen will, nimmt die Handles der Windows und das Zielrechteck entgegen, ändert die Größe der Windows und ruft MagSetWindowSource() der Magnification API auf, damit die aktuellen Pixeldaten des Zierechtecks in das Magnification Window kopiert werden. Danach wird dann meine Callback-Methode aufgerufen, welche die eigentlichen Pixeldaten empfängt.

Die zweite Routine, die ich immer aufrufe sieht so aus:


DLL void GetBitmapForRectangle(HWND magWindowHandle, HWND hostWindowHandle, long bitmapDataCallBackPointer, int startX, int startY, int width, int height) 
{
	RECT sourceRect;
	sourceRect.left = startX;
	sourceRect.top = startY;
	sourceRect.right = width;
	sourceRect.bottom = height;

	SetWindowPos(hostWindowHandle, HWND_TOPMOST, 0, 0, width, height, SWP_NOZORDER | SWP_NOACTIVATE);

	SetWindowPos(magWindowHandle, HWND_TOPMOST, 0, 0, width, height, NULL);


	MagSetWindowSource(magWindowHandle, sourceRect);
}

Ich hoffe jemand weiß da einen Rat. Selbst wenn ich die SetWindowPos() Methoden rausnehme, was natürlich zu einem falschen Ergebnis führt, wird es nicht merklich schneller, es liegt also an MagSetWindowSource() denke ich.

Ich hoffe das man trotz Window Desktop Manager so etwas noch umsetzen kann ohne diese Performance-Einbrüche.

5.658 Beiträge seit 2006
vor 10 Jahren

Wenn man das ziemlich oft macht und z.B. Hautpartien in einem großen Bild finden will

Dafür gibt es wesentlich bessere Möglichkeiten, siehe z.B. GetPixel und SetPixel um Längen geschlagen. 800 mal schneller

Christian

Weeks of programming can save you hours of planning

-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren

Hallo MrSparkle,

vielen Dank für die Anregung, den Thread auf den du dich beziehst habe ich seinerzeit auch verfolgt und nutze LockBits auch immer, ist nicht zu schlagen. Leider geht es mir nicht darum auf Pixeldaten einer vorhandenen Bitmap zuzugreifen, sondern es geht darum zunächst die Pixeldaten vom Screen (aus einem vorgegebenen Rechteck) in eine Bitmap zu bekommen.

Danach nutze ich bereits LockBits um die Pixeldaten der Bitmap auszuwerten.

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo -Hades-,

ist es evtl. schneller, statt viele kleiner(er) Bereiche vom Desktop zu lesen, die Daten auf einen Rutsch in eine Bitmap zu holen und dann aus dieser die gewünschten Bereiche auszulesen?

herbivore

-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren

Hallo Herbivore,

ja das ist im generellen Fall schneller, da die Zeiten für ein Rechteck von 1x1 Pixel nicht sehr stark von 100x100 abweichen.
Leider ist das jetzt nicht die super Lösung, da selbst wenn man immer den kompletten Screen oder eben einen größeren Bereich, in dem sich alles befindet was man untersucht, nimmt und dann per LockBits weiterarbeitet ist das schon nach ein paar Wiederholungen sehr viel lamgsamer im Vergleich zu Bitblt unter Windows 7 etc.

-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren

Ich wollte das Thema noch einmal kurz pushen, in der Hoffnung das doch noch jemand eine Idee hat das schneller hinzubekommen oder vielleicht hat jemand noch einen ganz anderen Ansatz für Windows 8...

Gruß -Hades-

-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren

Hat denn noch niemand Erfahrung bezüglich Windows 8? Ich weiß es ist schon recht speziell aber ich hoffe jemand hat noch eine Idee.