Windows GDI und WinAPI

Antworten
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

Windows GDI und WinAPI

Beitrag von schnullerbacke »

Hi all,

seh ich das richtig, das die WinAPI nur teilweise und die GDI garnicht in FPC/LAZARUS implementiert ist?

Ich hab hier gerade GIFImage von Anders Mellander beim Wickel. Die funzt bei Delphi ganz prima. Beim kompilieren fliegt die mir wegen fehlender API- und GDI-Aufrufen um die Ohren. Ich hab jetzt erstmal ne Dummy-Unit gebaut um die fehlenden Sachen rauszukriegen.

Mal gesetzt den Fall, irgendjemand ist ein echter Graphic-Freak, dann sollte sich das eventuell auf FPC/LAZARUS anpassen lassen. Setzt natürlich tiefgehende Kenntnis der Graphic-Libs von FPC/LAZARUS voraus. Durch die Hälfte vom Code komm ich schon durch.

Was ich jetzt nicht genau weiß ist, ob die Conversion-Errors (longint auf pointer umgestrickt) im FPC große Probleme bereiten? Die kommen massenweise.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

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

Re: Windows GDI und WinAPI

Beitrag von theo »

schnullerbacke hat geschrieben: Ich hab hier gerade GIFImage von Anders Mellander beim Wickel. Die funzt bei Delphi ganz prima. Beim kompilieren fliegt die mir wegen fehlender API- und GDI-Aufrufen um die Ohren. Ich hab jetzt erstmal ne Dummy-Unit gebaut um die fehlenden Sachen rauszukriegen.
Ich hatte mir das Ding auch mal angeschaut.
Wenn Du das crossplatform kriegst, dann bist du echt nicht schlecht.
Viel Spass dabei!

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 »

Hmmmm, sieht garnicht mal so schlecht aus.

Das ist einmal die Aufruferei der WinAPI-Fehlermeldungskiste, das sollte nicht so schwer sein.

Dann wären da die Paletten-Geschichten(GDI), da müßte mir mal jemand Tipps geben, das muß auf GTK umgestrickt werden.

Dann ist eine fehlende Funktion in der Graphics aufgetaucht, das seh ich mir an, bezieht sich aber auch auf Paletten.

Dann hab ich die anderen Fehler erstmal gelassen, das sind z.B. GDIFlush, da werd ich meine Probleme kriegen. Das muß man etwas besser wissen, wie sowas über LAZARUS/FPC zu ersetzen wäre.

Alles in allem 10 funktionen und ein paar externals, die ausgetauscht werden müssen.
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

Guck Dir das mal an und gib mir mal ein paar Hinweise, wenn dir dazu was einfällt. Der klatscht noch an der einen oder anderen Stelle auf, das ist aber Absicht damit man die fehlenden Methoden auch wiederfindet.
Dateianhänge
gifimage.zip
Anders Mellander GIFImage mit rudimentären Anpassungen und Dummy-Unit.
(277.3 KiB) 116-mal heruntergeladen
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

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

Beitrag von theo »

Das würde Dir so passen wa? Nee da musst du selber durch.
Ich will damit nichts zu tun haben! ;-)
Ausserdem habe ich heute und morgen programmierfrei.
Also fröhliche Weihnachten!

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 »

Na gut,

fröhliche Wiehnachten.

Falls die Neugier doch siegt, sieh Dir mal systemdummy.pas an. Da sind dummys für die fehlgeschlagenen Aufrufe der API und GDI drin. Da würden ein paar Hinweise bestimmt helfen. Z.B. sind die Paletten vergleichbar mit Colormap im GTK+?
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

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

Beitrag von theo »

schnullerbacke hat geschrieben:Na gut,

fröhliche Wiehnachten.

Falls die Neugier doch siegt, sieh Dir mal systemdummy.pas an. Da sind dummys für die fehlgeschlagenen Aufrufe der API und GDI drin. Da würden ein paar Hinweise bestimmt helfen. Z.B. sind die Paletten vergleichbar mit Colormap im GTK+?
Naja, ich hab mir das schon mal angeschaut. Sieht für mich nach Sackgasse aus.
Wenn es dich wirklich interessiert und du programmieren kannst hätt ich vielleicht was für dich. Ich bin nämlich seit einiger Zeit dran, eine Lösung für solche Probleme zu suchen. Ich bin den Plattform- und Pascal-dialekt-abhängigen Code nämlich dicke.
Hatte nur in den letzten zwei Monaten fast keine Zeit dafür.
Wenn Du mir beweist, dass du was kannst, dann schicke ich Dir den Code.
Dann machen wir das zusammen.
Was ich in die "Ehe" einbringen kann:

Ein völlig unabhängiges Bitmap, (TOPBitmap = TObjectPascalBitmap).
"Läuft" auf Delphi, Kylix, Lazarus. Benötigt keine externe Libraries. Funktioniert ohne X-Server auf Linux (für Services).
Es kann von pf1bit bis pf64bit alle Formate darstellen (mit Ausnahme von pf2bit).
Es kann alle Formate ineinander umwandeln. Es unterstützt optimierte Farbreduktion und Paletten. Auch Webpaletten sind unterstützt. Dithering gibt's nicht, weil ich das nicht mag (kann aber einer einbauen).
Alphablending und feines Resampling sind unterstützt.
Ich habe eine optimale BMP- schreib und lese Routine, die auch die "schrägen" Formate p15bit and pf16bit lesen und schreiben kann, besser als z.B Pixel (http://www.kanzelsberger.com/" onclick="window.open(this.href);return false;) welches übrigens auch mit FPC geschrieben ist.
Die BMP Unterstützung war meine "Lehrlingsprüfung" und ist nun ziemlich sauber.

Voll funktionsfähig ist auch bereits die JPEG schreib- und lese Routine (reines Pascal)
Angetestet und problemlos scheinend, aber mit Arbeit verbunden sind die Formate (reines Pascal):
PNG lesen OK/ PNG schreiben mit allen Varianten, auch Alpha blending.
GIF lesen OK / GIF schreiben mit Transparenz und Animation.
Alle Leseformate die GraphicEx unterstützt:
Kodak Photo CD, Adobe Photoshop (Hauptbild), Targa, TIFF (ohne TIFFJPEG), Paint Shop Pro, AutoDesk. SGI, PPM. etc. pp.

Ich habe von John M. Miano und Mike Lischke eine geschriebene Erlaubnis, ihren Code zu diesem Zweck zu verwenden. Ein paar rechtliche Abklärungen muss ich allerdings noch machen, und deshalb, und weil ich keine Zeit hab, veröffentliche ich den Code auch noch nicht offiziell.

Also beweis mal dass du was kannst, dann werden wir Partner! ;-)
Es gibt noch viel zu tun!
Nämlich alle oben genannten Formate in eine saubere Form bringen, und ein TOPGraphic bereitstellen welches alle Formate verwaltet etc.
Aber jedem Hanswurst gebe ich den Code jetzt noch nicht. ;-)

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 »

Soll das shared object laufen mit passender lib für verschiedene Sprachen? Das hätte was.

Also, ich hab jetzt in dem GIF-Image von A.M. die Dinger identifiziert die die Probleme machen. Das sind 2-3 Sachen in der Implementierung von TImage die man umgehen müßte, TBitmap.ScanLine sollte sich leicht nachbauen lassen, damit liest er das Canvas zeilenweise aus. Die Systemfehlermeldung von Windoofs dürfte das kleinste Problem sein. Bleibt die GDI. Ich hab mir GTK jetzt mal angesehen und die Docus dafür gezogen, die benutzen offenbar keine Paletten, die lazarus-Objects haben die Paletten offenbar auch nur abstract implementiert, das dürfte einige Probleme geben.

Nun mal kurz zum Hintergrund, ich hab da 2 Projekte laufen. Das eine soll der Goldesel werden um das 2te zu finanzieren. Das ist ein Chat-Server und Chat-Client die ohne den Script-Hokuspokus auskommen. Wegen der Optik im Client wären die GIF's ganz hübsch, deswegen ist mir daran gelegen. Die sind auch weitgehend beide fertig aber eben Client mit Delphi7 und Server mit Kylix3 prof.

Nun hab ich halt das Problem, das mein Kylix3 prof langsam aber sicher stirbt. Auf SuSE 10.1 ff krieg ich das nicht mehr zum laufen. Und ich hab auch keine rechte Lust immer alles 2mal zu machen, einmal VCL einmal CLX. Da ist zwar im Prinzip keine großes Problem solange man die Objekte selbst baut. Aber bei solchen Sachen wirds dann zum Problem.

Insbesondere deswegen, als ich Teile des Codes für das 2te Projekt, das ist ne Zahnarzt-Software, benutzen will. Dafür brauch ich aber eine Mimik, die es möglich macht auch Images per Stream zu übertragen. Die müssen trotzdem auslesbar sein. Der Hintergedanke dabei ist, die Praxen können ihre Patientendaten per DFÜ austauschen. Z.B. eben auch Röntgenbilder. Das streaming klappt schon prima und ließe sich auch verhältnismäßig einfach mit dem Kylix3-Client verarbeiten. Zusätzlich soll als Feature noch ne direkte Videoübertragung rein. Hintergrund ist die Schulung von Zahnarzthelferinnen, die ohne um den Stuhl rumstehen zu müssen, bestimmte Behandlungen am Bildschirm verfolgen können ohne dabei im Weg rumzustehen. Viel Platz haben die um so nen Behandlungsstuhl rum nicht. Aber es blieben 2 verschiedene Clients für Windoofs und LINUX (an MacOS mag ich garnicht denken), was ich gerne umgehen würde.

Deswegen FCP/Lazarus, das würde ne Menge Arbeit sparen und bietet auch die Aussicht, das auf 64-Bit anbieten zu können. Mehr oder weniger dürfte da neukompilieren reichen.

Der große Grafik-Freak bin ich nun nicht, ich habs mehr mit Datenbanken und Ablauflogik. Das soll nicht heißen, das ich mich da nicht einarbeiten könnte. Das wird wohl auch für die Zukunft nötig sein, wenn die Praxen-Software läuft wollte ich mich eigentlich mehr mit Grundlagen-Programmierung beschäftigen. Also mehr die Hilfs-Objekte bauen, damit man Anwendungen schneller basteln kann.

Da mein Freund, seines Zeichens Zahnarzt und spezialisiert auf Zahnersatz, über profundes Wissen verfügt, kann man sich da noch ne Menge vorstellen. Z.B. die Auswertung von Röntgenbildern und deren Darstellung in 3D. Das ist bei den Beißwerkzeugen nicht ganz einfach, die bestehen im Grunde aus einer Abfolge von Aufnahmen die dann 2D ausgegeben werden. Das in 3D umzurechnen dürfte schon etwas happig werden. Als nächstes wäre da die Planung von Zahnersatz, bei der man den Erfolg in 3D am Bildschirm direkt sehen kann. Das könnte man dem Patienten dann auch direkt so vorführen, damit er sieht was er für sein Geld bekommt, respektive wie er aussieht wenn er das nicht machen läßt. Das reicht bis zur Veränderung des Gesichtsausdrucks und der Kopfform (verkürztes Gesicht, weil der Kiefer weiter hochklappt...).

Also noch ein weites Feld, das man da beackern kann. Alleine dafür komm ich also nicht umhin, mich mit Grafik eingehender zu beschäftigen.

Allein mir fehlt die Zeit, ich muß das erste Ding jetzt langsam mal vom Tisch kriegen, das wäre schon schön.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

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

Beitrag von theo »

schnullerbacke hat geschrieben:Soll das shared object laufen mit passender lib für verschiedene Sprachen? Das hätte was.
Ähm, Nö. Wie kommst du nur immer auf so'n Schwachsinn?
Ich will auch von deinem Zeug rauchen.... ;-)

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 »

Zitat
...Pascal-dialekt-abhängigen Code nämlich dicke.
tatiZ

Pardon, der "-dialekt-" war mir abhanden gekommen... :oops:

Und von wegen "rauchen", das macht schlechte Zähne und was für Schlechte.
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

Willst Du für die Formate jeweils ein eigenes Objekt mit streaming bauen? Wenn Ja, wovon ableiten, TObject oder TPersistent?

Nächstes Problem, Bitmaps sind ziemlich groß. Sollen da auch MNG, AVI, SWF mit rein? Schränkt man damit nicht die Features wie Stretching und Proportional ein?

Ich hab mir das jetzt mal etwas näher angesehen und muß mir halt die Docus für die Formate noch zusammensuchen. Aber danach wäre wohl ne Ableitung von TPicture oder TCustomPicture das gegebene. Die sind auch bei Delphi ähnlich und können dann bei TImage eingehängt werden. Das würde es auch einfacher machen von einem in das andere Format zu konvertieren.

Das haste dir ja richtig was vorgenommen...

:lol:
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

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 »

ist ja ein tolles thema was ihr da habt.
ich befasse mich gerade mit der Grafik unter Lazraus.
Hinterrund ich möchte ein MS paint Clone schreiben mit erweiterten sachen.

Da währe so eine klasse garnicht mal so schlecht !
müst ihr euch dabei an ein standart halten ?
wenn nicht hätte ich eine idee:"abstracte klassen" *G*

mein größter wunsch ist es immer gewesen direct bin dateien auszulesen und zu verarbeiten !
evlt. werde ich mich damit befassen dann kann ich euch in ein paar wochen helfen !

das gleiche habe ich mit sound dateien vor *G*
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 »

TGraphic ist die abstrakte Klasse, davon ist z.B. TBitmap abgeleitet. Die lassen sich alle TPicture zuweisen und dann wird das dargestellt. Man muß halt die richtige Vaterklasse nehmen um davon abzuleiten. Grafik-Dateien haben ne genormte Endung (.png, .xmp, .bmp...), trotzdem unterscheiden die sich dann noch in ihren Formaten. Die haben aber dann ne Mime-Kennung in den ersten bytes anhand derer man das richtige Format herausbekommt. Dann muß man das entsprechend beim einlesen zerlegen.

Ist also schon ziemlich heftig.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

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

Beitrag von theo »

schnullerbacke hat geschrieben: Willst Du für die Formate jeweils ein eigenes Objekt mit streaming bauen? Wenn Ja, wovon ableiten, TObject oder TPersistent?
Im Moment sieht's so aus:

Code: Alles auswählen

{$IFDEF IMPORTTGRAPHIC}
{$I tgraphicdecl.inc}
{$ELSE}
  TGraphic = class(TPersistent)
  end;
{$ENDIF}
 
  TOPBitmap = class(TGraphic)
schnullerbacke hat geschrieben: Nächstes Problem, Bitmaps sind ziemlich groß. Sollen da auch MNG, AVI, SWF mit rein?
Nein.
schnullerbacke hat geschrieben: Ich hab mir das jetzt mal etwas näher angesehen und muß mir halt die Docus für die Formate noch zusammensuchen. Aber danach wäre wohl ne Ableitung von TPicture oder TCustomPicture das gegebene.
Nö, TPicture ist ja in Graphics.pas (pp) deklariert.
Sobald du das drin hast, hast du Abhängigkeiten von LCL/CLX/VCL und damit auch vom X-Server unter Linux d.h. läuft nicht mehr für Server ohne X.
Mein ganzer Code läuft nur mit der RTL / FCL ohne LCL etc.
Bitmaps brauchen das ja nicht unbedingt. Das sind ja im Grunde nur Arrays und Schreib-Lese Algorithmen.
Auf den Screen kommt die ganze Geschichte (wenn überhaupt) erst ganz am Schluss z.B. über Scanline, LazIntfImage, oder durch speichern und laden eine BMP. Man kann auch über DIB zeichnen (Windows) oder gdk_draw_rgb_image (GTK)
schnullerbacke hat geschrieben: Das haste dir ja richtig was vorgenommen...
Ja, läuft aber schon. Jetzt geht's nur noch darum, viele Schreib-Lese Formate einzubauen und das Interface zu säubern, naja und Bugfixes ;-)

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

Beitrag von theo »

Also falls es jemanden wirklich interessiert, zeige ich mal kurz einen Auschnitt am Beispiel von pf16bit. Hier kann man sehen wie das ganze in etwa funktioniert.
Vielleicht sagt das mehr als 1000 Worte ;-)

Array Typ für 16 Bit Bitmaps

Code: Alles auswählen

Pixel16 = Word;
  APixel16 = array[0..MaxArr] of Pixel16;
  PAPixel16 = ^APixel16;


Deklaration für TBitmapData

Code: Alles auswählen

{ TBitmapData }
 
  TBitmapData = class
  private
    fBPP: Byte;
    fParent: TOPBitmap;
    fWidth: Integer;
    fHeight: Integer;
    fLineLength: Integer;
    function GetScanLine(Row: Integer): Pointer; virtual; abstract;
    function GetPixel(X, Y: Integer): TColor; virtual; abstract;
    procedure SetPixel(X, Y: Integer; const Value: TColor); virtual; abstract;
    procedure SetWidth(const Value: Integer); virtual;
    procedure SetHeight(const Value: Integer); virtual;
  protected
    procedure UpdateSize; virtual; abstract;
    function CheckPixelValid(X, Y: integer): Boolean;
  public
    constructor Create(Parent: TOPBitmap); virtual;
    destructor Destroy; override;
    property Pixels[X, Y: Integer]: TColor read GetPixel write SetPixel;
    property ScanLine[Row: Integer]: Pointer read GetScanLine;
    property BPP: byte read fBPP;
    property Width: Integer read fWidth write SetWidth;
    property Height: Integer read fHeight write SetHeight;
    property LineLength:integer read fLineLength;
  end;
Deklaration für TBitmapData16

Code: Alles auswählen

{ TBitmapData16 }
 
  TBitmapData16 = class(TBitmapData)
  private
    fPixels: PAPixel16;
    function GetScanLine(Row: Integer): Pointer; override;
    function GetPixel(X, Y: Integer): TColor; override;
    procedure SetPixel(X, Y: Integer; const Value: TColor); override;
  protected
    procedure UpdateSize; override;
  public
    constructor Create(Parent: TOPBitmap); override;
    property RawArray: PAPixel16 read fPixels write fPixels;
    property NativePixels[X, Y: Integer]: TColor read GetPixel write SetPixel;
  end;
Implementation für TBitmapData16

Code: Alles auswählen

{ TBitmapData16 }
 
constructor TBitmapData16.Create(Parent: TOPBitmap);
begin
  inherited;
  fBPP := 16;
end;
 
 
function TBitmapData16.GetPixel(X, Y: Integer): TColor;
var idx: Cardinal;
  R, G, B: Byte;
begin
  if not CheckPixelValid(X, Y) then exit;
  idx := Y * fWidth + X;
 
  R := (fPixels^[idx] and $F800) shr 11;
  G := (fPixels^[idx] and $7E0) shr 5;
  B := (fPixels^[idx] and $1F);
 
  if (R = $1F) then R := $FF else if (R <> 0) then R := (R + 1) shl 3;
  if (G = $3F) then G := $FF else if (G <> 0) then G := (G + 1) shl 2;
  if (B = $1F) then B := $FF else if (B <> 0) then B := (B + 1) shl 3;
 
  Result := (B shl 16) + (G shl 8) + R;
end;
 
function TBitmapData16.GetScanLine(Row: Integer): Pointer;
begin
  Result := @fPixels[Row * fWidth];
end;
 
procedure TBitmapData16.SetPixel(X, Y: Integer; const Value: TColor);
var idx: Cardinal;
begin
  if not CheckPixelValid(X, Y) then exit;
  idx := Y * fWidth + X;
  fPixels^[idx] := ((Pixel32(Value).Blue shr 3) shl 11) or
    ((Pixel32(Value).Green shr 2) shl 5) or
    ((Pixel32(Value).Red shr 3) shl 0);
end;
 
procedure TBitmapData16.UpdateSize;
begin
  if (fWidth > 0) and (fHeight > 0) then
  begin
    fLineLength := fWidth * 2;
    GetMem(fPixels, fHeight * fLineLength)
  end else
    if (fPixels <> nil) then begin
      FreeMem(fPixels);
      fPixels := nil;
    end;
end;
Deklarationsanfang für TOPBitmap

Code: Alles auswählen

TOPBitmap = class(TGraphic)
  private
    fData: TBitmapData;    
  etc, etc...

Antworten