Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   GDI Größenbeschränkung? (https://www.delphipraxis.net/188438-gdi-groessenbeschraenkung.html)

striderx 3. Mär 2016 17:05

GDI Größenbeschränkung?
 
Hallo zusammen,

ich benutze folgende Prozedur, um Bitmaps zu drehen und zu zoomen (und danach auf einen tImage abzubilden):

Delphi-Quellcode:
procedure TdlgMain.RotateImage;

var
  svMode:   Integer;
  vMatrix:  tagXFORM;
  svMatrix: tagXFORM;
  vSine:    Extended;
  vCosine:  Extended;
  vAngle:   Double;
  vOffsetX: Integer;
  vOffsetY: Integer;
  Z:        Double;

begin
  bmEasel.Height            := bmCustom.Height;
  bmEasel.Width             := bmCustom.Width;
  bmEasel.Canvas.Brush.Style := bsSolid;
  bmEasel.Canvas.Brush.Color := clWhite;
  bmEasel.Canvas.Fillrect(bmEasel.Canvas.ClipRect);
  {......................................................................}
  vAngle  := sbAngle.Position;
  vOffsetX := sbOffsetX1.Position;
  vOffsetY := sbOffsetY1.Position;
  Z       := sbZoom1.Position / 100;
  {......................................................................} 
  svMode := SetGraphicsMode(bmEasel.Canvas.Handle, GM_ADVANCED);
  if (svMode = GM_ADVANCED) then
     GetWorldTransform(bmEasel.Canvas.Handle, svMatrix);
  {......................................................................} 
  FillChar (vMatrix, SizeOf(vMatrix), 0);
  vMatrix.em11 := 1.0;
  vMatrix.em22 := 1.0;
  vMatrix.eDx := -(vOffsetX + bmEasel.Width / 2);
  vMatrix.eDy := -(vOffsetY + bmEasel.Height / 2);
  SetWorldTransform(bmEasel.Canvas.Handle, vMatrix);
  {......................................................................} 
  SinCos (vAngle * Pi / 180, vSine, vCosine);
  FillChar (vMatrix, SizeOf(vMatrix), 0);
  if Z = 1 then begin
     vMatrix.em11 := vCosine;
     vMatrix.em12 := vSine;
     vMatrix.em21 := -vSine;
     vMatrix.em22 := vCosine;
  end
  else begin
     vMatrix.em11 := Z * Cos(0.0174532925199433 * vAngle);
     vMatrix.em12 := Z * Sin(0.0174532925199433 * vAngle);
     vMatrix.em21 := -Z * Sin(0.0174532925199433 * vAngle);
     vMatrix.em22 := Z * Cos(0.0174532925199433 * vAngle);
  end;
  ModifyWorldTransform(bmEasel.Canvas.Handle, vMatrix, MWT_RIGHTMULTIPLY);
  {......................................................................} 
  FillChar (vMatrix, SizeOf(vMatrix), 0);
  vMatrix.em11 := 1.0;
  vMatrix.em22 := 1.0;
  vMatrix.eDx := (vOffsetX + bmEasel.Width / 2);
  vMatrix.eDy := (vOffsetY + bmEasel.Height / 2);
  ModifyWorldTransform(bmEasel.Canvas.Handle, vMatrix, MWT_RIGHTMULTIPLY);
  {......................................................................}   
  bmEasel.Canvas.Draw(vOffsetX, vOffsetY, bmCustom);
  {......................................................................} 
  if (svMode = GM_ADVANCED) then
     SetWorldTransform(bmEasel.Canvas.Handle, svMatrix)
  else SetGraphicsMode(bmEasel.Canvas.Handle, svMode);
  {......................................................................}
  FitBitmap(bmEasel, iEaselShow);
end;

procedure FitBitmap(Source: tBitmap; Dest: tImage);

var
  R:  Double;

begin
  if Dest.Height < Dest.Width then R := Dest.Height / Source.Height
  else R := Dest.Width / Source.Width;
  try
    ScaleImage(Source, Dest.Picture.Bitmap, R);
  except
  end;
end;
Den wesentlichen Teil der Prozedur habe ich hier http://www.delphipraxis.net/526724-post9.html in der DP gefunden, die Ergänzung fürs Zoomen hier http://www.delphipraxis.net/1295365-post10.html.

Das Pixelformat der beiden Bitmaps ist pf24bit (explizit gesetzt), das Ganze läuft unter Windows 7 64 und XE 6.

Was ist nun mein Problem: Rotieren und Zoomen funktionieren schnell und problemlos bis zu einer Bitmap-Größe von unter 9 Mio Pixel. Mit 9 Mio Pixel wird es erratisch (klappt mal (dann sehr lange Laufzeit) klappt mal nicht), bei noch größeren Biptmaps passiert überhaupt nichts. D. h., dass auch kein Fehler ausgeworfen wird, auch ist das Ergebnis der verwendeten GDI-Funktion immer True.

Ich habe auch nach längeren Suchen nichts zu diesem Problem oder einer GDI Größenbeschränkungen gefunden.

Hat einer von euch eine Idee?

Medium 7. Mär 2016 00:17

AW: GDI Größenbeschränkung?
 
Bitmaps sind GDI-seitig auf 65536x65536 Pixel beschränkt, aber das ist ja noch weit weit über deiner Größe von quasi 3000x3000. (Diese Begrenzung habe ich irgendwann mal beim Stöbern in den Seiten von MS gefunden, war bisher aber nicht in der Lage dazu dies wiederzufinden :()
Mit knapp 35MB kommst du eigentlich auch noch lange nicht an irgendwelche brenzlige Speichergrenzen. Ich sehe auch nichts was direkt ins Auge stechen würde im Code. Gibt der Taskmanager evtl. etwas mehr Aufschluss? Explodierender Speicherbedarf, oder plötzlich Unmengen an verbrauchten Handles oder sowas? Was sagt die CPU dazu wenn es gerade mal länger dauert?

striderx 7. Mär 2016 08:32

AW: GDI Größenbeschränkung?
 
Wenn es länger dauert, geht die CPU-Last um 25 - 30% hoch, die Anzahl der Handles verändert sich nicht wesentlich, der Speicherbedarf scheint mir normal zu sein. Wenn es nicht längere dauert, ist die Prozedur ratz fatz durchlaufen - nur ohne Ergebnis halt.

Was mir bei den Langläufern auffällt: Im Task-Manager ist das Programm dann der CPU 25 zugeordnet, was bei einer Vier-Kern-CPU natürlich verwundert. Das könnte aber daran liegen, dass das Programm während der Aussführung der Prozedur keine Rückmeldung gibt.

Sir Rufo 7. Mär 2016 09:28

AW: GDI Größenbeschränkung?
 
Wer so etwas schreibt
Delphi-Quellcode:
  try
    MachIrgendwas();
  except
  end;
und sich dann wundert, wenn es mal kein Ergebnis gibt, gehört IMHO geteert und gefedert :stupid:

Also weg mit dem unsinnigen und blinden Wegfangen der Exceptions und schau, was der Rechner dir zu sagen hat (und ob).

Zacherl 7. Mär 2016 10:12

AW: GDI Größenbeschränkung?
 
Ist das hier von der Logik her wirklich so gewollt, dass die Matrix nur dann retrieved wird, wenn der ALTE GraphicsMode
Delphi-Quellcode:
GM_ADVANCED
war?
Delphi-Quellcode:
svMode := SetGraphicsMode(bmEasel.Canvas.Handle, GM_ADVANCED);
if (svMode = GM_ADVANCED) then
  GetWorldTransform(bmEasel.Canvas.Handle, svMatrix);
Denn laut MSDN liefert dir MSDN-Library durchsuchenSetGraphicsMode als Result:
Zitat:

If the function succeeds, the return value is the old graphics mode.

striderx 7. Mär 2016 16:13

AW: GDI Größenbeschränkung?
 
@Sir Rufo
Da hab ich ja Glück gehabt, dass du micht nicht noch anzünden willst. ;-)
Aber ernsthaft: Da stand natürlich vorher etwas drin, ich habe nur vergessen, den try Block auch noch zu löschen. Ein Fehler ist an dieser Stelle übrigens nicht ausgeworfen worden.

@Zacherl
Der ursprüngliche Autor (s. Link in meinem Eingangspost) hat das so kommentiert, dass hier der aktuelle Grafik-Modus zwischengespeichert und dann nach Abschluss der Operation wieder restauriert wird.

Ich habe jetzt mal nachgesehen: Bei mir ist der Graphic-Modus nie GM_Advanced. Wenn der Modus aber nicht ausgelesen und später mit

Delphi-Quellcode:
SetGraphicsMode(bmEasel.Canvas.Handle, svMode);
nicht wieder gesetzt wird, erfolgt keine Drehung, auch bei kleineren Bitmaps nicht.


@alle: Es wäre natürlich toll, wenn das mal jemand bei sich laufen lassen würde, um zu schauen, ob das Problem auch woanders auftritt.



"now we are still confused but we are confused on a higher level"

striderx 3. Apr 2016 10:43

AW: GDI Größenbeschränkung?
 
Vielleicht interssieret es ja jemanden:

Der Fehler tritt unter Windows 7 auf - nicht aber unter Windows 10.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:17 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz