AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Bilder [mit/ohne Transparenz] in universelles Format bringen

Bilder [mit/ohne Transparenz] in universelles Format bringen

Offene Frage von "Jens01"
Ein Thema von berens · begonnen am 16. Aug 2016 · letzter Beitrag vom 17. Aug 2016
Antwort Antwort
Seite 3 von 3     123
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.163 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#21

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 16. Aug 2016, 16:29
Dann sollte doch nach einem glBindTexture über Quader diese sich verkleinern lassen.

Oder sehe ich da was falsch?
Das Problem war, dass die Bilder z.T. sehr groß sind und nicht in den GPU-Speicher passen, bzw. diesen überlasten.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#22

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 16. Aug 2016, 16:34
Dann sollte doch nach einem glBindTexture über Quader diese sich verkleinern lassen.

Oder sehe ich da was falsch?
Das Problem war, dass die Bilder z.T. sehr groß sind und nicht in den GPU-Speicher passen, bzw. diesen überlasten.
Ahh ok

gruss
  Mit Zitat antworten Zitat
berens

Registriert seit: 3. Sep 2004
421 Beiträge
 
Delphi 2010 Professional
 
#23

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 16. Aug 2016, 16:55
Also wie gesagt, das eigentliche Laden und Umwandeln von Graphiken klappt nun, das sogar sehr gut und schnell.

Jetzt habe ich vorhin groß getönt, dass ich mich um das verkleinern im PowerOf2-Maßstab kümmere... Tja...

Mit dem jetzigen Code
Delphi-Quellcode:
  ms := TMemoryStream.Create;
  ms.Position := 0;
  wic := TWICImage.Create;
  wic.LoadFromFile(_Filename);
  ResizeImage(wic, TexturWidth, TexturHeight);
  wic.ImageFormat := wifPng;
  wic.SaveToStream(ms);
  ms.Position := 0;
  LoadFromStream(ms);
  FreeAndNil(ms);

  GenTexture(True); // geladene Textur an OpenGL übergeben
wird die Graphik tatsächlich auf eine sinnvolle Texturgröße geschrumpft, allerdings haben nun -situationsbezogen- die X- und Y-Achsen unterschiedliche Skalierungen. Textur Width/Height sind ja ein vielfaches von 2, also 2^x, und meist sind die Texturen quadratisch. Somit würde nun, wenn ich das Bild stupide render, alle Bilder die nicht exakt quadratisch sind, in Höhe oder Breite gequetscht oder auseinandergezogen erscheinen (verzerrt).

Eigentlich wollte ich auf die (quadratischen) Texturen die Graphik im richtigen Seitenverhältnis größtmöglich zeichnen, und den -wegen Seitenverhältnis- ungenutzten Bereich dann zukünftig beim rendern einfach ignorieren (ich merke mir Breite und Höhe des "wirklichen" Bildes auf der Textur).

Jetzt habe ich das Problem, dass das Bild (verzerrt) auf der ganzen Textur vollflächig dargestellt wird (ich stauche ja die komplette Graphik aus egal welchem Seitenverhältnis z.B. auf 2048x1024). Andererseits kann man das auch positiv sehen: Eine Seite der Textur wäre ja eh vollständig genutzt worden (Breite oder Höhe), weil das Bild ja nicht auf beiden Achsen kleiner gemacht wird, als die Textur ist; wäre ja auch Quatsch. Auf der anderen Achse (also nun die verbleibende Höhe oder Breite) bleiben nun durch das nicht-beibehalten des Seitenverhältnisses mehr "Bildinformationen" von der ursprünglichen Graphik mit vll. 20'000px über, d.h. auf der kompletten Breite habe ich nun 2048 Pixel vom Originalbild über anstatt vielleicht nur 2000. Wenn man die Graphik später auf dem Bildschirm noch kleiner darstellt ist vielleicht die Skalierung einen Hauch feiner, als ohne die beispielhaften 48px? Es könnte natürlich auch sein, dass es um so schlimmer aussieht? Meinungen?

Wie könnte ich mit WICImage Stretchdraw durchführen, es hat ja keinen Canvas...?

@bytecook:
> Bild via LoadPng it ein TBitmap32 laden.
Ja was passiert denn, wenn es eine .tif oder .jpg-Datei ist. Geht dann LoadPNG trotzdem?

> Bild auf gewünschte Größe resamplen. (Am besten je nach Geschmack/Quali mit einem Lanczos Resampler). Die meisten Lowlevel-Routinen in Gr32 sind SSE2 optimiert, also seeeehr schnell...
Sollte irgendwie gehen.

> Bild auf GlBitmap via Scanline übertragen.
Da wird's schon wieder lustig, weil ich habe keine Ahnung, wie das gehen soll. TglBitmap2d bietet meines Wissens keine ScanLine an, weil es ja kein TBitmap oder so in dem Sinne ist.
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#24

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 16. Aug 2016, 17:13
Zitat:
Da wird's schon wieder lustig, weil ich habe keine Ahnung, wie das gehen soll. TglBitmap2d bietet meines Wissens keine ScanLine an, weil es ja kein TBitmap oder so in dem Sinne ist.
Ich denke schon..

function TglBitmap2D.GetScanline(Index: Integer): Pointer;

gruss
  Mit Zitat antworten Zitat
Benutzerbild von bytecook
bytecook

Registriert seit: 6. Aug 2010
Ort: Dornbirn
143 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#25

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 16. Aug 2016, 17:26
Zitat:
Da wird's schon wieder lustig, weil ich habe keine Ahnung, wie das gehen soll. TglBitmap2d bietet meines Wissens keine ScanLine an, weil es ja kein TBitmap oder so in dem Sinne ist.
Ich denke schon..

function TglBitmap2D.GetScanline(Index: Integer): Pointer; gruss
Ja, es gibt sogar in einem meiner vorherigen Posts einen speziellen Link mit einer überladenen Methode für GR32 dazu. Siehe: https://delphigl.com/forum/viewtopic...hics32#p100074

CTOP!

Delphi-Quellcode:
     
    uses [...] {$IFDEF GLB_DELPHI}           Dialogs, Graphics, Types, GR32, {$ENDIF} [...]
     
    function TglBitmapData.AssignFromBitmap(const aBitmap: TBitmap32): Boolean;
    var
      pSource: PColor32Array;
      pData, pTempData: PByte;
      Row, RowSize, TempWidth, TempHeight: Integer;
      IntFormat: TglBitmapFormat;
    begin
      result := false;
     
      if (Assigned(aBitmap)) then
      begin
        IntFormat := tfBGRA8ub4;
        TempWidth := aBitmap.Width;
        TempHeight := aBitmap.Height;
        RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
        GetMem(pData, TempHeight * RowSize);
     
        try
          pTempData := pData;
          for Row := 0 to TempHeight -1 do
          begin
            pSource := aBitmap.Scanline[Row];
            if (Assigned(pSource)) then
            begin
              Move(pSource^, pTempData^, RowSize);
              Inc(pTempData, RowSize);
            end;
          end;
          SetData(pData, IntFormat, TempWidth, TempHeight);
          result := true;
        except
          if Assigned(pData) then
            FreeMem(pData);
          raise;
        end;
      end;
    end;

@berens: <Ja was passiert denn, wenn es eine .tif oder .jpg-Datei ist. Geht dann LoadPNG trotzdem?>
Nomen est omen?

Dafür hat man dann andere (in meinem Falle) <native> Importroutinen, oder nimmt halt das TWicImage. Ich bin ja davon ausgegangen, dass du korrekte Skalierung benötigst, da beim
Bitmap-Resizen große Verluste entstehen. Deswegen bevorzuge ich TBitmap32...

> Bild auf GlBitmap via Scanline übertragen.
<Da wird's schon wieder lustig, weil ich habe keine Ahnung, wie das gehen soll. TglBitmap2d bietet meines Wissens keine ScanLine an, weil es ja kein TBitmap oder so in dem Sinne ist>

Eine Bitmap hat nicht unbedingt was mit einem Bild zu tun - eher eine zweidimensionale Speichermöglichkeit. Eine TBitmap beherbergt ja auch nur ein zweidimensionales Bytearray für die Pixelinfo plus einen Header. Das Bildformat im Header bestimmt dann, wieviele Bytes pro Pixel verwendet werden. In unserem Falle bei Gr32 oder glBitmap intern immer 32 Bit, deswegen sind die Scanlines auch schön nett kompatibel Die greift übrigens dann direkt auf den Lowlevel Bildbuffer zu und ist entsprechend schnell.

Und zu den Texturen und deren Position: Dazu musst du dann ggf auch mal UV Mapping generell verstehen. Richard hat da ein paar nette Tutorials für Modo... https://vimeo.com/ondemand/uvmapping/168397312
Peter

Geändert von bytecook (16. Aug 2016 um 17:43 Uhr)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.624 Beiträge
 
Delphi 2007 Enterprise
 
#26

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 16. Aug 2016, 18:17
Nur kurz am Rande: Power-of-two Texturen sind seit ca. DirectX 9 Zeiten keine Notwendigkeit mehr, so dass praktisch jede GPU die nicht älter als 10 Jahre ist damit klar kommen sollte.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
berens

Registriert seit: 3. Sep 2004
421 Beiträge
 
Delphi 2010 Professional
 
#27

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 16. Aug 2016, 20:37
Zu "TFormatDescriptor" finde ich leider auch über Google nichts, bzw. dieser Thread hier ist schon auf Platz 3 der Suchergebnisse. Deshalb funktioniert die verlinkte Prozedur nicht. Was genau verwendest du da?

Ausserdem musste ich einiges anpassen:
Delphi-Quellcode:
function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap32): Boolean;
var
  pSource: PColor32Array;
  pData, pTempData: PByte;
  Row, RowSize, TempWidth, TempHeight: Integer;
  IntFormat: TglBitmapInternalFormat;
begin
  result := false;

  if (Assigned(aBitmap)) then
  begin
    IntFormat := ifBGRA8; // hier
    TempWidth := aBitmap.Width;
    TempHeight := aBitmap.Height;
    RowSize := trunc(FormatGetSize(IntFormat) * TempWidth); // hier
    GetMem(pData, TempHeight * RowSize);

    try
      pTempData := pData;
      for Row := 0 to TempHeight -1 do
      begin
        pSource := aBitmap.Scanline[Row];
        if (Assigned(pSource)) then
        begin
          Move(pSource^, pTempData^, RowSize);
          Inc(pTempData, RowSize);
        end;
      end;
      SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //hier
      result := true;
    except
      if Assigned(pData) then
        FreeMem(pData);
      raise;
    end;
  end;
end;
Das Ganze wird soweit korrekt dargestellt, die Frage ist halt, ob Alles rechnerisch bzw. Inhaltlich richtig ist. Leider muss man diese Prozedur direkt in die glBitmap-Unit einbinden, da einige interne Prozeduren verwendet werden, die von außerhalb der Unit nicht erreichbar sind (naja, die kann man ja kopieren oder über Deklarationen nach Außen verfügbar machen.


Hiermit kann ich nun die Graphik tatsächlich proportional verkleinert auf die Textur zeichnen, aktuell noch unschön mit tmpImage:
Delphi-Quellcode:
  bmp32 := TBitmap32.Create;
  bmp32.Width := TexturWidth;
  bmp32.Height := TexturHeight;
  bmp32.Canvas.StretchDraw(Rect(0, 0, ImageWidth, ImageHeight), tmpImage.Picture.Graphic);

  AssignFromBitmap(bmp32);
  GenTexture(True);
Bitte mal gegenlesen ob das insgesamt passt. Ich versuche dann später noch das "SmoothResize" aus den GR32-Units zu verwenden und dann hier noch zu posten.

-- Aktuell sieht es so gut aus! Sowohl .bmp und .png werden korrekt dargestellt, die anteilige Verwendung der Texturen scheint auch zu klappen, dass muss ich nochmal im Detail morgen testen. --

Übrigens hat der TWICImage-Loader lustigerweise bei dem Test mit einer 18'000 x 13'648 Graphik mit Exception versagt. TImage/TPicture hat jedoch problemlos geklappt. (Ich glaube Euch, dass die GR32-Loader besser/stabiler sind/sein können, aber wenn's so funktioniert... Warum nicht?)

Nochmal großes Dank an Alle!
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
  Mit Zitat antworten Zitat
Benutzerbild von bytecook
bytecook

Registriert seit: 6. Aug 2010
Ort: Dornbirn
143 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#28

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 17. Aug 2016, 10:16
> Das Ganze wird soweit korrekt dargestellt, die Frage ist halt, ob Alles rechnerisch bzw. Inhaltlich richtig ist. Leider muss man diese Prozedur direkt in die glBitmap-Unit einbinden, da einige interne Prozeduren verwendet werden, die von außerhalb der Unit nicht erreichbar sind (naja, die kann man ja kopieren oder über Deklarationen nach Außen verfügbar machen.

Hmmm - wenn die Routinen als Protected deklariert sind, kannst du ja mittels Trick drauf zugreifen...

Deklariere einfach in deiner Unit unter der Implementation folgenden Typ:

TGlBitmapAccess = Class(TGlBitmap);

danach kannst du mittels TGlBitmapAccess(Variable).methode Cast drauf zugreifen, oder, noch schöner, leite dir eine neue Klasse Klasse dafür ab und override / overloade die AssignFromBitmap Routine.
Peter

Geändert von bytecook (17. Aug 2016 um 10:20 Uhr)
  Mit Zitat antworten Zitat
berens

Registriert seit: 3. Sep 2004
421 Beiträge
 
Delphi 2010 Professional
 
#29

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 17. Aug 2016, 11:34
Ok, einen essenziellen Fehler habe ich gefunden, der letztentlich auch erklären würde, warum die komplette Aktion mit TBitmap vielleicht nicht funktioniert hat:
Wenn ich nun eine nicht-transparente Graphik lade, wird Diese unter keinen Umständen angezeigt. K.a. warum mir das gestern Abend nicht aufgefallen ist.

Ich habe nun den Loader wie folgt angepasst:
Delphi-Quellcode:
   bmp32 := TBitmap32.Create;
   bmp32.Width := TexturWidth;
   bmp32.Height := TexturHeight;
   bmp32.Canvas.StretchDraw(Rect(0, 0, ImageWidth, ImageHeight), tmpPicture.Graphic);
   if not tmpPicture.Graphic.Transparent then begin
     bmp32.ResetAlpha;
   end;

   AssignFromBitmap(bmp32);
Auf den ersten Blick scheint mir Graphic.Transparent tatsächlich zuverlässig zu sagen, ob die geladene Datei mit oder ohne Transparenzinformationen kommt. Zumindest ein .bmp, .png-mit und .png-ohne hat er korrekt unterschieden. Wenn nun also eine Graphik ohne Alpha kommt, wird mit .ResetAlpha jeder Pixel auf "sichtbar" gesetzt. Scheint aktuell zu klappen?

Für die Schönheit und den Seelenfrieden der Community habe ich übrigen endlich TImage durch TPicture ausgetauscht
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
623 Beiträge
 
#30

AW: Bilder [mit/ohne Transparenz] in universelles Format bringen

  Alt 17. Aug 2016, 13:49
@berens
Bitte stell die Änderungen noch mal ins DelphiGL Forum bei GLBitmap ein. Hat sich da vlt etwas bei TglBitmap geändert?
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 +2. Es ist jetzt 03:52 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf