Windows GDI und WinAPI

Antworten
Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Stimmt auch wieder über den Namen hab ich mir noch nie Gedanken gemacht.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

Auf Linux ist mir klar, das Pendant auf Windoofs kanns nicht. Habs probiert, animated GIF's werden als Ebenen angezeigt, MNG garnicht (libmng ist installiert).

Im Übrigen regelt das Kylix auch über die Qt, die kann das Format und erkennt das beim einlesen selbst. Gibt keinen Anlass anzunehmen, das Gimp das anders machen sollte. Wenns aber nicht da ist (MNG, JNG scheint zu fehlen), dann kann Gimp eben auch nicht.

Von der Logik her gehören solche Formate eigentlich auch in die Desktop-Lib, das mag zwar auf den ersten Blick unflexibel sein, für Standardformate macht es aber Sinn.

Hat jemand von euch schonmal versucht TNGImage auf Lazarus zu portieren? Ich hab das gerade mal unter Kylix3 prof installiert, läuft ganz prima. Das sollte sich also verhältnismäßig einfach portieren lassen, so man sich mit den Grafik-Lib's von FPC/Lazarus gut auskennt. Das stellt MNG, JNG und zusätzlich noch JPEG und NGBitmap z.V.. Für LINUX wird lediglich statt stdcall cdecl angewendet. Ansonsten wird das über TPicture eingehängt.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Benutzeravatar
theo
Beiträge: 10861
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Christian hat geschrieben:Stimmt auch wieder über den Namen hab ich mir noch nie Gedanken gemacht.
http://de.wikipedia.org/wiki/GIMP-Toolkit" onclick="window.open(this.href);return false;

Und übrigens: Das mit den Masken zum transparenten Zeichnen des OPBitmap auf Win/GTK habe ich langsam im Griff. Das ist halt einfach ein Haufen Feinarbeit.

Während auf GTK ein Maskenbild im Grunde ein "straight" Bitmap (1bit) ist, muss man auf Windows die Bits in jedem Byte "umdrehen", damit's stimmt:

Code: Alles auswählen

function ReverseBits(b:Byte):Byte;
var c:Byte;
begin
  c:=b;
  c := ((c shr  1) and $55) or ((c shl  1) and $aa);
  c := ((c shr  2) and $33) or ((c shl  2) and $cc);
  c := ((c shr  4) and $0f) or ((c shl  4) and $f0);
  result:=c;
end;
Zusätzlich muss man auf Win die Linienlängen des Maskenbilds noch auf Word Boundary bringen.

Knifflig aber machbar.

Aber ein Problem habe ich noch: Ich kriege bei manchen Bildern eine total fiese Zugriffsverletzung unter Laz, nicht Kylix. Reproduzierbar mit diesen Bildern aber normalerweise läuft's
Und zwar ganz am Schluss, wenn das Bild im Prinzip gezeichnet ist, beim Freigeben des OPBitmap.
Hat jemand aus Erfahrung oder so Brainstormmässig einen verdacht was das sein könnte?
Bzw, warum macht nur FPC dieses Problem?
Bin für Tipps dankbar, weil ich im Moment nicht dahinterkomme.

Code: Alles auswählen

procedure TBitmapData32.UpdateSize;
begin
  if (fWidth > 0) and (fHeight > 0) then
  begin
    fLineLength := fWidth * 4;
    if (fPixels <> nil) then FreeMem(fPixels);
    GetMem(fPixels, fHeight * fLineLength)
  end else
    if (fPixels <> nil) then begin
      FreeMem(fPixels);  <!--- hier SEGFAULT
      fPixels := nil;
    end;
end;

[font=Courier New]TApplication.HandleException Access violation
Stack trace:
$080641E3
$08064250
$0806426A
$0806488B
$080648DF
$08063B00
$081F7444 TBITMAPDATA32__UPDATESIZE, line 1154 of opbitmap.pas
$081F5627 TBITMAPDATA__DESTROY, line 633 of opbitmap.pas
$0805D855
$081F7EA1 TOPBITMAP__DESTROY, line 1332 of opbitmap.pas
$081FB286 TCANVASOPBITMAP__DESTROY, line 2478 of opbitmap.pas
$081FC7A7 TJPEGIMAGE__DESTROY, line 141 of opbitmapformats.pas
$0805D855
$0807834C TFORM1__BUTTON1CLICK, line 95 of unit1.pas
$081107D6 TCONTROL__CLICK, line 1948 of ./include/control.inc
$081649AD TBUTTONCONTROL__CLICK, line 57 of ./include/buttoncontrol.inc
$08166401 TCUSTOMBUTTON__CLICK, line 187 of ./include/buttons.inc




^running

(gdb)

*stopped,reason="signal-received",signal-name="SIGSEGV",signal-meaning="Segmentation fault",thread-id="1",frame={addr="0x080641e3",func="SYSTEM_CONCAT_TWO_BLOCKS$PMEMCHUNK_VAR$PMEMCHUNK_VAR",args=[]}

(gdb)


^done,depth="53"

(gdb)


^done,stack-args=[frame={level="0",args=[]}]

(gdb)


^done,stack=[frame={level="0",addr="0x080641e3",func="SYSTEM_CONCAT_TWO_BLOCKS$PMEMCHUNK_VAR$PMEMCHUNK_VAR"}]

(gdb)


^done,stack-args=[frame={level="1",args=[]}]

(gdb)


^done,stack=[frame={level="1",addr="0x08064250",func="SYSTEM_TRY_CONCAT_FREE_CHUNK_FORWARD$PMEMCHUNK_VAR"}]

(gdb)


^done,stack-args=[frame={level="2",args=[]}]

(gdb)


^done,stack=[frame={level="2",addr="0x0806426a",func="SYSTEM_TRY_CONCAT_FREE_CHUNK$PMEMCHUNK_VAR$$PMEMCHUNK_VAR"}]

(gdb)


^done,stack-args=[frame={level="3",args=[]}]

(gdb)


^done,stack=[frame={level="3",addr="0x0806488b",func="SYSTEM_SYSFREEMEM_VAR$PMEMCHUNK_VAR$$LONGINT"}]

(gdb)


^done,stack-args=[frame={level="4",args=[]}]

(gdb)


^done,stack=[frame={level="4",addr="0x080648df",func="SYSTEM_SYSFREEMEM$POINTER$$LONGINT"}]

(gdb)


^done,stack-args=[frame={level="5",args=[]}]

(gdb)


^done,stack=[frame={level="5",addr="0x08063b00",func="SYSTEM_FREEMEM$POINTER$$LONGINT"}]

(gdb)


^done,stack-args=[frame={level="6",args=[{name="this",value="(^TBITMAPDATA32) 0x40027e98"}]}]

(gdb)


^done,stack=[frame={level="6",addr="0x081f7444",func="TBITMAPDATA32__UPDATESIZE",file="opbitmap.pas",line="1154"}]

(gdb)




[/font]

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

@theo

Dein fPixels war doch als Array of BlaBla deklariert? Da hätte ich mal das GetMem im Verdacht, das scheint den Speicher für die Struktur so zu verkürzen, das der bereits am Ende ankommt bevor der letzte Eintrag gelöscht wird (#0). Ich würde das lieber als Array mit SetLength machen. Eine Möglichkeit besteht darin, das GetMem Byte-oriented reseviert während das Array auf Word ausrichtet, dann hast du künstlich das Array verkürzt und er klatscht auf.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Benutzeravatar
theo
Beiträge: 10861
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

schnullerbacke hat geschrieben:@theo
Dein fPixels war doch als Array of BlaBla deklariert? Da hätte ich mal das GetMem im Verdacht, das scheint den Speicher für die Struktur so zu verkürzen, das der bereits am Ende ankommt bevor der letzte Eintrag gelöscht wird (#0). Ich würde das lieber als Array mit SetLength machen. Eine Möglichkeit besteht darin, das GetMem Byte-oriented reseviert während das Array auf Word ausrichtet, dann hast du künstlich das Array verkürzt und er klatscht auf.
Hmm, ja Danke für die Anregung. Ich werde das mit SetLength (Dynarray) vielleicht auspobieren müssen

Was gegen deine Vermutung spricht:

- Wenn so was nicht geht (bei FPC), warum dann nur bei 5% der Bilder, die sich z.B. nicht durch extreme Grösse von anderen unterscheiden? Sollte das dann nicht immer in die Hose gehen?

- Mit den Byte: Aber gerade das 32bit Bitmap richtet doch "von Natur aus" auf Doubleword (4 Byte) aus. Also daran wird's wohl kaum liegen.

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

Nö, nicht unbedingt. Das könnte bei 8-Bit schief gehen, bei 16,24,32 gehts dann gut. Da ist die word-Ausrichtung implizit durch die Größe gegeben.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Benutzeravatar
theo
Beiträge: 10861
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

schnullerbacke hat geschrieben:Nö, nicht unbedingt. Das könnte bei 8-Bit schief gehen, bei 16,24,32 gehts dann gut. Da ist die word-Ausrichtung implizit durch die Größe gegeben.
Sag ich ja. Ich spreche aber von 32 bit.

Übrigens: Ich habe jetzt eine "Lösung" gefunden. Keinen blassen Schimmer wieso aber so geht alles:

Code: Alles auswählen

procedure TBitmapData32.UpdateSize;
begin
  if (fWidth > 0) and (fHeight > 0) then
  begin
    fLineLength := fWidth * 4;
    if (fPixels <> nil) then FreeMem(fPixels);
    GetMem(fPixels, fHeight * fLineLength+1) <-- Ein einziges Byte mehr reservieren
  end else
    if (fPixels <> nil) then begin
      FreeMem(fPixels);
      fPixels := nil;
    end;
end;
Wenn ich EIN Byte mehr reserviere ist alles Paletti.
//Todo: Sich fragen wieso?

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Im Übrigen regelt das Kylix auch über die Qt, die kann das Format und erkennt das beim einlesen selbst. Gibt keinen Anlass anzunehmen, das Gimp das anders machen sollte. Wenns aber nicht da ist (MNG, JNG scheint zu fehlen), dann kann Gimp eben auch nicht.
Wie jetzt ? weil Borland die ja auch n windows programm gegen die wine bibliotheken linken damits so aussäh als sei es n linux programm das so macht müssen alle anderen das auch so machen die logik versteh ich nicht sorry.
Von der Logik her gehören solche Formate eigentlich auch in die Desktop-Lib, das mag zwar auf den ersten Blick unflexibel sein, für Standardformate macht es aber Sinn.
gtk,qt und co sind keine desktop libs sondern widgetsets die sind lediglich dazu da um benutzeroberflächen zu zeichen weiter nix da gehören keine dateifoprmate rein, wenn qt das macht is gut aber für lazaruzs macht das gar keinen sinn die zu nutzen da lazarus widgetsetunabhängig ist.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

@Christian

Kylix nutzt die Qt-Lib für seine Oberfläche. Für dein fertiges Proggi brauchste kein Wine, nur die Qt-Lib's mußte mitliefern. Die Qt-Lib kann GIF, auch animated, deswegen funzt das bei Kylix mit dem normalen TImage, während du für Delphi zusätzliche sourcen brauchst (etwa Anders Mellander GIFImage). Für MNG, JNG, PNG gilt bei Delphi das gleiche, bei Kylix nur für MNG, JNG.

Das macht mir ja das Leben so schwer. Idealerweise sollten diese Klamotten vom Development-System z.V. stehen und das für beide OS. Ich hab einfach keinen Bock mehr, jedesmal unterschiedliche Sourcen nur wegen solcher halbgaren Vorgaben zu haben. Dabei ist es Schißkujennum ob das nun von der Dekstop-Lib kommt oder im Quelltext OS-unabhängig läuft, nur laufen muß es.

@theo

0tes Byte nicht mitgezählt?
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

@theo

Ich würd's trotzdem mit SetLength über dem Array machen. Sonst bekommst du eventuell bei 8- und 24-Bit Probleme damit. Die könnten beide durch word-alignment mit GetMem genau den Käse produzieren. Mal abgesehen davon, das man mit nem Index, weil ganzzahlig, auch verhältnißmäßig schnell ist, das braucht kaum Prozessor-Takte (3 mein ich). Bei Adress-Rechnung sieht das schon anders aus. Beim Array geht er über den Offset, das könnte deutliche Geschwindigkeitsvorteile bringen, von der Sicherheit mal ganz abgesehen.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

schmeiss nicht n dynamisches array und n array durcheinander, n dynamisches array braucht mindestens genauso viel rechenzeit wie wenn du getmem nimmst da man mit getmem noch die kontrolle hat alles auf einen schlag zu holen und somit nen nicht segmentierten speicherbereich bekommt das array kann das schon mit realloc machen
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
theo
Beiträge: 10861
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Christian hat geschrieben:schmeiss nicht n dynamisches array und n array durcheinander, n dynamisches array braucht mindestens genauso viel rechenzeit wie wenn du getmem nimmst da man mit getmem noch die kontrolle hat alles auf einen schlag zu holen und somit nen nicht segmentierten speicherbereich bekommt das array kann das schon mit realloc machen
Ja mei, ich probiers mal aus mit dem dynamischen Array. Schneller wird das aber kaum sein.
Ich hatte es ursprünglich nicht damit gemacht, weil ich irgendwo gelesen habe FPC hätte noch seine Problemchen damit. Ausserdem war mir das Reference Counting für meine Zwecke eher suspekt, das ich den Speicher sowieso selber freigeben möchte.

Wie Verhalten sich denn Dynamische Arrays mit z.B. Move befehlen? Problemlos?

Warum ich's Probiere: Um die Hypothese mit dem word-alignment zu testen.
Zuletzt geändert von theo am Mi 31. Jan 2007, 19:02, insgesamt 2-mal geändert.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

nur weil es bei einem anderen Programm nicht geht, sollte man nicht auf eine Funktion versichetet werden. oder wenn es anders gemacht wird/wurde !

wenn es eine Möglichkeit gibt Platform übergreifend Grafiken/Animationen/Videos
anzuzeigen währe das schon toll !

(Wenn ich euch Richtig verstanden habe)
MFG
Michael Springwald

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

Bei move verhält sich das genauso wie ein statisches array, nur kannst du da wohl nicht mit SizeOf arbeiten, das wirst du wohl per (High(array) + 1) * SizeOf(arg) oder ähnlich machen müssen.

Bei Adressrechnung hab ich irgendwas mit 11-12 Prozessortakte im Hinterkopf, da ist ganzzahlige Arythmetik klar im Vorteil. Entscheidend ist aber bei wechselnden Größen ganz sicher das Alignment.

Aber wenn's denn unbedingt GetMem sein soll, dann bezieh das nicht auf ein dynamisches Array, dann rechne lieber selber und allozier den Speicher dann. Hat natürlich den Nachteil der Rechnerei, ansonsten bliebe nur eine verkettete Pointerliste. Die letzte Methode ist allerdings nicht jedermanns Sache.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Ich wäre mit dem move auch vorsichtig auf ein element sicher lich problemlos aber wenns über mehrere gehen soll wirds früher oder später access violations hageln schliesslich ist nicht geregelt wie die speicherbelegung innerhalb des arrays auszusehn hat bei nem statischen array ist das klar

@schnullerbacke ich habe nie gesagt das man wine braucht um kylix applikationen auszuführen
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Antworten