AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Grenzen von PlgBlt

Ein Thema von Schwedenbitter · begonnen am 5. Mai 2009 · letzter Beitrag vom 22. Nov 2010
Antwort Antwort
Seite 2 von 2     12   
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#11

Re: Grenzen von PlgBlt

  Alt 6. Mai 2009, 08:41
Hab mal schnell was geschrieben:
Delphi-Quellcode:
procedure Rotiere(ABitmap: TBitmap; ADirection: Integer);
{---}
const
  PIXELCOUNT = 8;
{---}
  function Rol(const AByte, APositions: Byte): Byte register;
  asm
    mov cl, dl
    rol al, cl
  end;
{---}
  function Ror(const AByte, APositions: Byte): Byte register;
  asm
    mov cl, dl
    ror al, cl
  end;
{---}
  function CalcByteCount(AWidth: Integer): Integer;
  begin
    Result := AWidth div PIXELCOUNT;
    if (AWidth mod PIXELCOUNT) > 0 then
      Inc(Result);
  end;
{---}
var
  y, x1, x2, yMax, i, xCount, yCount: Integer;
  p1, p2, buffer: ^Byte;
  v, m: Byte;
begin
  {im Uhrzeigersinn drehen}
  if (ADirection = 90) or (ADirection = 180) or (ADirection = 270) then
  begin
    ABitmap.Pixelformat := pf1Bit;

    xCount := CalcByteCount(ABitmap.Width);
    yCount := CalcByteCount(ABitmap.Height);

    GetMem(buffer, xCount * yCount * PIXELCOUNT);
    try
      FillChar(buffer^, xCount * yCount * PIXELCOUNT, #0);

      yMax := ABitmap.Height - 1;

      if ADirection = 90 then
      begin
        m := 1 shl (PIXELCOUNT - 1);
        for y := yMax downto 0 do
        begin
          p1 := ABitmap.Scanline[y];
          p2 := buffer;
          Inc(p2, (yMax - y) div PIXELCOUNT);
          for x1 := 0 to xCount - 1 do
          begin
            v := p1^;
            for x2 := 0 to PIXELCOUNT - 1 do
            begin
              v := Rol(v, 1);
              if Odd(v) then
                p2^ := p2^ or m;
              Inc(p2, yCount);
            end;
            Inc(p1, 1);
          end;
          m := Ror(m, 1);
        end;
        ABitmap.SetSize(ABitmap.Height, ABitmap.Width);
        p2 := buffer;
      end
      else if ADirection = 270 then
      begin
        m := 1 shl (PIXELCOUNT - 1);
        for y := 0 to yMax do
        begin
          p1 := ABitmap.Scanline[y];
          Inc(P1, xCount - 1);
          p2 := buffer;
          Inc(p2, (y div PIXELCOUNT));
          for x1 := 0 to xCount - 1 do
          begin
            v := p1^;
            for x2 := 0 to PIXELCOUNT - 1 do
            begin
              if Odd(v) then
                p2^ := p2^ or m;
              v := Ror(v, 1);
              Inc(p2, yCount);
            end;
            Dec(p1, 1);
          end;
          m := Ror(m, 1);
        end;
        ABitmap.SetSize(ABitmap.Height, ABitmap.Width);
        p2 := buffer;
        {Leerzeilen überspringen}
        Inc(p2, yCount * ((xCount * PixelCount) - ABitmap.Height));
      end
      else if ADirection = 180 then
      begin
        p2 := buffer;
        i := (ABitmap.Width mod PIXELCOUNT);
        for y := yMax downto 0 do
        begin
          p1 := ABitmap.Scanline[y];
          Inc(P1, xCount - 1);
          if i = 0 then
            v := 0
          else
          begin
            v := p1^;
            Dec(p1);
            v := Rol(v, i);
          end;
          for x1 := 0 to xCount - 1 do
          begin
            m := 0;
            for x2 := 0 to i - 1 do
            begin
              m := Rol(m, 1);
              if Odd(v) then
                m := m or 1;
              v := Ror(v, 1);
            end;
            if (i > 0) and (x1 = (xCount - 1)) then
              v := 0
            else
            begin
              v := p1^;
              Dec(P1);
            end;
            for x2 := i to PIXELCOUNT - 1 do
            begin
              m := Rol(m, 1);
              if Odd(v) then
                m := m or 1;
              v := Ror(v, 1);
            end;
            p2^ := m;
            Inc(p2);
          end;
        end;
        p2 := buffer;
      end
      else
        Exit;
      {Bitmap aus dem Buffer füllen}
      xCount := CalcByteCount(ABitmap.Width);
      for y := 0 to ABitmap.Height - 1 do
      begin
        p1 := ABitmap.Scanline[y];
        Move(p2^, p1^, xCount);
        Inc(p2, xCount);
      end;
    finally
      FreeMem(Buffer);
    end;
  end;
end;
Edit: Hoffe es ist einfach genug.
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#12

Re: Grenzen von PlgBlt

  Alt 6. Mai 2009, 13:55
Zitat von Blup:
Hab mal schnell was geschrieben:
Edit: Hoffe es ist einfach genug.
Ich bedaure, es nicht zu verstehen. Aber das für mich wichtige funktioniert. Nur nebenbei: Das Drehen um 180° klappt bei mir nicht. Das brauche ich aber auch nicht. Jedenfalls ist es die schnellste Routine, die ich probiert habe und das sind immerhin 4 an der Zahl und sie benutzt neben Assembler keine externen Funktionen. 3 Routinen funktionieren ganz gut und 1 (PlgBlt) klappt nicht mit großen Bildern <-- meine Ausgangsfrage.

Ich habe nur gedacht, dass die Funktionen von GDI+ übersichtlich sind. Das sind sie wohl auch. Kürzer und einfacher als FlipBild.RotateFlip(Rotate90FlipNone); ist ja kaum vorstellbar. Aber wenn ich erhebliche Klimmzüge starten muss, um mein TBitmap in alle möglichen anderen Typen und wieder zurück zu verwandeln, dann ist es für mich nicht nutzbar.
Ich wäre gern bei GDI+ geblieben bzw. erstmal dorthin gekommen, weil ich das Bild vor/nach dem Drehen noch strecken bzw. stauchen muss. Und dafür scheint es ja auch Einiges bereit zu halten ...

Vielen herzlichen Dank sagt Alex
Alex Winzer
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#13

Re: Grenzen von PlgBlt

  Alt 6. Mai 2009, 14:12
Zitat:
Ich wäre gern bei GDI+ geblieben bzw. erstmal dorthin gekommen, weil ich das Bild vor/nach dem Drehen noch strecken bzw. stauchen muss. Und dafür scheint es ja auch Einiges bereit zu halten ...
Ja es ist nicht einfach habe auch sehr viel lesen müssen.
Für mich war es etwas einfacher da es unter VB viele anleitungen und samples gibt von denen man lernen kann.
In Delphi gibt es da fast so gut wie nichts.

Was du am ende benutzt mußt du selbst wissen.
Es soll ja funktionieren.

gruss Emil
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#14

Re: Grenzen von PlgBlt

  Alt 6. Mai 2009, 18:01
Zitat von EWeiss:
Ja es ist nicht einfach habe auch sehr viel lesen müssen.
Für mich war es etwas einfacher da es unter VB viele anleitungen und samples gibt von denen man lernen kann.
In Delphi gibt es da fast so gut wie nichts.

Was du am ende benutzt mußt du selbst wissen.
Es soll ja funktionieren.

gruss Emil
Dass es für Delphi nur wenig Unterstützung gibt, habe ich schon festgestellt. VB kann ich leider nicht und habe auch nicht die Zeit, mich da einzuarbeiten. Die VB-Anleitungen habe ich auch gefunden. Aber es ist sehr schwer, das nach Delphi zu übertragen.

Aber ich bin doch tatsächlich ein gutes Stück weiter. Mein Vorteil ist, dass ich die Bilder "nur" verarbeiten und dann speichern muss. Das Darstellen usw. ist für mich unwichtig. Und so ist es mir zwischenzeitlich gelungen, mein TBimap einem TGPBitmap zuzuweisen und nach anfägnlichen Schwierigkeiten auch zu speichern. Ich habe den Code als Archiv angehängt für Interessierte.

Dazu habe ich eine Frage:
1. Mit der Funktion
Delphi-Quellcode:
GDIPBitmap:=TGPBitmap.Create(Image1.Picture.Bitmap.Handle,
                             Image1.Picture.Bitmap.Palette);
sage ich - nach meinem Verständnis -, dass GDIPBitmap den Speicherbereich von Image1.Picture.Bitmap benutzen soll. Da aber Image1 den Speicher nicht freigibt, müssten die Operationen, die ich mache auch Image1 betreffen und evtl. sogar angezeigt werden. Wo liegt mein Missverständnis?

Gruß und Danke für die Vorschlage, Hilfen und Ermunterungen

Alex
Angehängte Dateien
Dateityp: zip gdip_p_156.zip (2,0 KB, 10x aufgerufen)
Alex Winzer
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#15

Re: Grenzen von PlgBlt

  Alt 7. Mai 2009, 08:03
Zitat von Schwedenbitter:
Nur nebenbei: Das Drehen um 180° klappt bei mir nicht.
Seltsam, bei mir funktioniert auch das fehlerlos.
Habs auch mit deiner großen Bitmap probiert.
Was genau klappt den nicht, bzw. wie sieht das Ergebnis aus?
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#16

AW: Re: Grenzen von PlgBlt

  Alt 22. Nov 2010, 14:02
Hallo,

mit der Zeit werde auch ich schlauer und habe somit gelernt, wie man DLL-Funktionen einbinden kann . Ich habe jetzt in den Implementations-Teil meiner "Dreh-Unit" folgendes geschrieben:
Delphi-Quellcode:
Const
  Status = (Ok, GenericError, InvalidParameter, OutOfMemory,
ObjectBusy, InsufficientBuffer, NotImplemented, Win32Error, WrongState, Aborted, FileNotFound, ValueOverflow, AccessDenied, UnknownImageFormat, FontFamilyNotFound, FontStyleNotFound, NotTrueTypeFont, UnsupportedGdiplusVersion, GdiplusNotInitialized, PropertyNotFound, PropertyNotSupported);
  TStatus = Status;
  GpStatus = TStatus;

Function GdipImageRotateFlip(Image: Pointer;
   rfType: ROTATEFLIPTYPE): GPSTATUS; Stdcall; External 'gdiplus.dll';
Die Deklaration von RotateFlipType habe ich jetzt mal außen vor gelassen. Die Deklaration von GPStatus ist nicht auf meinem Mist gewachsen, sonder ich habe sie einfach aus der Unit GDIPAPI.pas von progdigy übernommen.
Und so sollte das dann von mir aufgerufen werden:
Delphi-Quellcode:
Procedure TMainForm.BtnRotateClick(Sender: TObject);
Var
  Stat      : GPStatus;
  tmp      : HBitmap;
Begin
  tmp:=Image1.Picture.Bitmap.Handle;
  Stat:=GdipImageRotateFlip(@tmp, Rotate90FlipNone);
  ShowMessage(StatusText[Stat]);
End;
TImage.Picture.Bitmap.Handle ist doch vom Typ HBITMAP. Ist das eine anderes HBITMAP als es GDI+ benutzt?
Denn ich bekomme immer die Statusmeldung "ObjectBusy" zurück. Erwartet hatte ich eigentlich "GdiplusNotInitialized", weil ich genau das nicht getan habe; Initialisieren.

Könnte mir bei der Gelegenheit bitte mal jemand ein Beispiel posten, wie ich mit den Funktionen "GdipCreateBitmapFromHBITMAP" bzw. "GdipCreateHBITMAPFromBitmap" ein TBitmap aus Delphi in ein GDI+-konformes HBITMAP umwandeln kann und umgekehrt?

Mehr als das und "GdipImageRotateFlip" brauche ich vermutlich wirklich nicht, so dass mein Code übersichtlich und mein Programm schön klein bliebe!

Bitte, bitte, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#17

AW: Re: Grenzen von PlgBlt

  Alt 22. Nov 2010, 17:23
Der "falsche" Fehlercode kommt wohl daher, dass ich GDI+ nicht initialisiert hatte. Jetzt klappt es mit dem Erzeugen durch GdipCreateBitmapFromHBITMAP() . Der Status passt und der Pointer auf das Image ist nicht mehr nil .

Allerdings erhalt ich nun beim Aufruf von GdipImageRotateFlip als Status-Rückmeldung InvalidParameter wobei folgendes definiert ist:
Delphi-Quellcode:
Type
  RotateFlipType= (RotateNoneFlipNone = 0,
                   Rotate90FlipNone = 1,
                   Rotate180FlipNone = 2,
                   Rotate270FlipNone = 3,
                   RotateNoneFlipX = 4,
                   Rotate90FlipX = 5,
                   Rotate180FlipX = 6,
                   Rotate270FlipX = 7,
                   RotateNoneFlipY = Rotate180FlipX,
                   Rotate90FlipY = Rotate270FlipX,
                   Rotate180FlipY = RotateNoneFlipX,
                   Rotate270FlipY = Rotate90FlipX,
                   RotateNoneFlipXY = Rotate180FlipNone,
                   Rotate90FlipXY = Rotate270FlipNone,
                   Rotate180FlipXY = RotateNoneFlipNone,
                   Rotate270FlipXY = Rotate90FlipNone);
  Status = (Ok, GenericError, InvalidParameter, OutOfMemory,
                   ObjectBusy, InsufficientBuffer, NotImplemented,
                   Win32Error, WrongState, Aborted, FileNotFound,
                   ValueOverflow, AccessDenied, UnknownImageFormat,
                   FontFamilyNotFound, FontStyleNotFound,
                   NotTrueTypeFont, UnsupportedGdiplusVersion,
                   GdiplusNotInitialized, PropertyNotFound,
                   PropertyNotSupported);
  TStatus = Status;
  GpStatus = TStatus;
Auch das stammt nicht von mir, sondern ist ein Ausschnitt aus der von mir bereits zitierten Unit.

Was mache ich denn nun wieder falsch?

Mein Ziel ist es nachwievor, einfach nur ein TBitmap herzunehmen, in ein GDI+Bild umzuwandeln, dieses zu drehen und dann wieder in ein TBitmap zurückzuwandeln.
Alex Winzer
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#18

AW: Re: Grenzen von PlgBlt

  Alt 22. Nov 2010, 23:15
Ich antworte nun mal selbst:

ich habe es mit den Funktionen hinbekommen. Offenbar gelten die Grenzen von PlgBlt() bedauerlicher Weise auch für GdipImageRotateFlip() . Die Ursache für die Speicherzugriffsverletzungen und sonstigen Fehlermeldungen war schlicht die, dass mein Test-Bild zu groß ist. Benutze ich ein kleineres Bild, dann klappt das ganze prima.
Es gibt bloß ein Speicherleck, dass ich mit FastMM nicht eingrenzen kann. Bei jedem Drehen, braucht das Programm mehr Speicher und FastMM zeigt beim Beenden rein garnichts an. Ich habe sogar schon Speicherlecks provoziert, die gezeigt werden. Aber der andere Verbrauch ist unergründlich.

Da ich also die API von Windows wohl vergessen kann, muss ich mir jetzt überlegen, wie ich den Code von Blup so aufbohre, dass er auch für Bilder mit pf24bit funktioniert.

Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#19

AW: Grenzen von PlgBlt

  Alt 22. Nov 2010, 23:33
Ich nutze GID+ sehr ausgiebig, allerdings mit Streams und Painroutinen, falls Du schnelle und einfache Canvasroutinen brauchen solltest, kann du ja hie mal bohren und erweitern:
Delphi-Quellcode:
unit ExCanvasTools;
// 20100915 by Thomas Wassermann
interface
uses
  Windows, SysUtils, Classes, Graphics;

  Function Grad2Rad(w:Double):Double;
  Procedure PaintGraphic(ACanvas:TCanvas;x,y:Integer;AGraphic:TGraphic;Faktor,Winkel:Double;PosIsCenter:Boolean=false);
  Procedure PaintText(ACanvas:TCanvas;Const s:String;x,y:Integer;Faktor,Winkel:Double;PosIsCenter:Boolean=false);
  Procedure ResetCanvas(ACanvas:TCanvas);
  procedure SetCanvasZoomAndRotation(ACanvas: TCanvas;Zoom:Double;Angle:Double;CenterpointX,CenterpointY:Double);

implementation

Function Grad2Rad(w:Double):Double;
  begin
     Result := w / 360 * PI *2;
  end;

Procedure PaintText(ACanvas:TCanvas;Const s:String;x,y:Integer;Faktor,Winkel:Double;PosIsCenter:Boolean=false);
var
  px,py:Integer;
begin
     SetCanvasZoomAndRotation(ACanvas , Faktor, Winkel, x,y);
     if PosIsCenter then
        begin
          px := Round( ACanvas.TextWidth(s) / 2 );
          py := Round( ACanvas.TextHeight(s) / 2 );
        end
     else
        begin
          px := 0;
          py := 0;
        end;

     ACanvas.TextOut(-px ,-py ,s);
     ResetCanvas(ACanvas);
end;




Procedure PaintGraphic(ACanvas:TCanvas;x,y:Integer;AGraphic:TGraphic;Faktor,Winkel:Double;PosIsCenter:Boolean=false);
var
  px,py:Integer;
begin
     if PosIsCenter then
        begin
          px := Round( AGraphic.Width / 2 );
          py := Round( AGraphic.Height / 2 );
        end
     else
        begin
          px := 0;
          py := 0;
        end;
     SetCanvasZoomAndRotation(ACanvas , Faktor, Winkel, x , y );
     ACanvas.Draw(-px ,-py ,AGraphic);
     ResetCanvas(ACanvas);
end;





Procedure ResetCanvas(ACanvas:TCanvas);
begin
   SetCanvasZoomAndRotation(ACanvas , 1, 0, 0,0);
end;

Procedure SetCanvasZoomAndRotation(ACanvas:TCanvas;Zoom:Double;Angle:Double;CenterpointX,CenterpointY:Double);
var
    form : tagXFORM;
    Winkel:Double;

begin
      Winkel := Grad2Rad(Angle);
      SetGraphicsMode(ACanvas.Handle, GM_ADVANCED);
      SetMapMode(ACanvas.Handle,MM_ANISOTROPIC);
      form.eM11 := Zoom * cos( Winkel);
      form.eM12 := Zoom *Sin( Winkel) ;
      form.eM21 := Zoom * (-sin( Winkel));
      form.eM22 := Zoom * cos( Winkel) ;
      form.eDx := CenterpointX;
      form.eDy := CenterpointY;
      SetWorldTransform(ACanvas.Handle,form);
end;

end.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


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 23:20 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