AGB  ·  Datenschutz  ·  Impressum  







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

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
Benutzerbild von Neutral General
Neutral General

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

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

  Alt 16. Aug 2016, 12:43
Also erstmal würde ich kein TImage benutzen. Das ist nämlich (wenn du das im DelphiGL-Forum schon ansprichst) unprofessionell
Wenn der Benutzer ein Bild auswählt erzeuge anhand der Dateiendung ein Objekt der entsprechenden TGraphic-Klasse (TPNGImage, TBitmap, ...).
Schau dann ob, die jeweilige TGraphic-Klasse eine Möglichkeit bietet das Bild in der Größe zu ändern und danach gehst du wie bei deinem Versuch mit TPNGImage vor und speicherst das verkleinerte Bild in einem Stream und übergibst diesen dann an OpenGL.
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
 
#2

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

  Alt 16. Aug 2016, 12:51
Zitat:
D.h. ich muss alle Graphiken auf 24Bit reduzieren, und das würde also bedeuten, dass ich alle TransparenzInformationen verliere?
Davon kannst du ausgehen keine 32Bit beim *.bmp dann ist die Transparenz futsch.
Das Problem ist du hast zwar viel geschrieben aber dein Anliegen kann ich jetzt nicht direkt ersehen.

Was möchtest du also?
Unabhängig vom Format!
Lade ein Bild und erstelle dann ein neues direkt aus dem Speicher.
Transparent oder was auch immer.

Ich hab da mal was in C# gemacht vielleicht hilft es dir ja.

Code:
  ///<summary>
  ///Graphics related funcs
  ///</summary>
  [SuppressUnmanagedCodeSecurity]
  public sealed class PicFromMem
  {

    private static bool GetImageFromBytes(byte[] data, out Image image)
    {
      try
      {
        using (var ms = new MemoryStream(data))
        {
          image = Image.FromStream(ms);
        }
      }
      catch (ArgumentException)
      {
        image = null;

        return false;
      }

      return true;
    }

    private static Image RemoveMetadata(byte[] data)
    {
      Image image;

      if (GetImageFromBytes(data, out image))
      {
        Bitmap bitmap = new Bitmap(image);

        using (var graphics = Graphics.FromImage(bitmap))
        {
          graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
          graphics.CompositingMode = CompositingMode.SourceCopy;
          graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

          graphics.DrawImage(image, 0, 0);
        }
        return image;
      }

      return null;
    }
    ///<summary>
    /// Get Image from Memory Pointer
    ///</summary>
    ///<returns>
    ///Image from Byte Array without MetaData
    ///</returns>
    public static Image GetImageFromMemPtr(IntPtr DataPtr, long Size)
    {
      byte[] bArray = new byte[Size];

      Marshal.Copy(DataPtr, bArray, 0, (int)Size);

      // Remove MetaData from File
      return RemoveMetadata(bArray);

    }
  }

gruss

Geändert von EWeiss (16. Aug 2016 um 13:27 Uhr)
  Mit Zitat antworten Zitat
berens

Registriert seit: 3. Sep 2004
441 Beiträge
 
Delphi 10.4 Sydney
 
#3

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

  Alt 16. Aug 2016, 13:42
> Was möchtest du also?

Ich möchte wissen, ob es ein universelles Objekt (ala TBitmap) gibt, von dem aus ich eine Graphik in TglBitmap2D verwandeln kann.


Spätestens wenn ich TBitmap voll ausreize und auf 32-Bit gehe, geht das ganze ja schon wieder nicht. Von PNG _kann_ TglBitmap2D aber 32-Bit (incl. Alpha) übernehmen. Was gibt es also besseres als TBitmap?

TPicture hatte halt den angenehmen vorteil, dass ich mich als solches nicht um das Dateiformat kümmern brauche. Wenn das (auch zukünftige) Betriebssystem die Bilder laden kann ist gut, Bibliotheken für JPG und PNG ergänzen den Rest. Wenn ich nun wirklich für _jeden_ Dateityp eine eigene Ableitung von TGraphic berücksichtigen muss (sofern es einen gibt!), muss ich erst mal wissen welche das sind (Wo steht das?) und welche es alles gibt (BMP, JPG, PNG, TIF, PCX, GIF, ...). Dafür, dass TPicture schon Alles "von Haus aus" (mithilfe der Bibliotheken) kann, steigert das separate verarbeiten nach TGraphic unterschieden -meines Erachtens(!)- das die Fehleranfälligkeit, erhöht unnötig die Redundanz aber leider nicht die Sicherheit, da ja TglBitmap2D leider je nach Pixelformat etc. trotzdem nicht mit allen Varianten von TGraphic zurechtkommt. Deshalb würde ich gerne 100% sicher sein, dass die von mir aufbereitete Graphik _vor_ der übergabe an OpenGL/TglBitmap2D garantiert in einem Datei-/Pixel-/Graphikformat ist (auch mit RGB<-->BGR Problematik), was später problemlos von TglBitmap2D verarbeitet werden kann.

Gerne speichere ich es als TPNGImage zwischen, aber da kommt ja die Fehlermeldung. Das genau werde ich jetzt nochmal detaillierter und hier im Forum suchen, das Oben nur mal als Zwischenbericht.

Danke nochmal; für weitere Tips habe ich die Ohren offen.

Edit: Da unten ging dein Beitrag ja noch weiter mit Code, den schaue ich mir an. Danke.
  Mit Zitat antworten Zitat
Benutzerbild von bytecook
bytecook

Registriert seit: 6. Aug 2010
Ort: Dornbirn
151 Beiträge
 
Delphi 11 Alexandria
 
#4

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

  Alt 16. Aug 2016, 13:50
Würde Graphics32 (www.graphics32.org in Kombination mit (gr32_png) einsetzen.

Aktuelle GR32 Version: https://github.com/graphics32/graphics32 (Support inkl. 10.1 Berlin)
Aktuelles Png Lib: https://sourceforge.net/projects/gr32pnglibrary/

Damit hast du mal die Basis, GR32 arbeitet per se mit 24 Bit Farbtiefe + 8 Bit Alphachannel.
Du kannst auch jederzeit einem TBitmap32 ein "normales" Bitmap zuordnen.

Gruß,

Peter
Peter

Geändert von bytecook (16. Aug 2016 um 13:59 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#5

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

  Alt 16. Aug 2016, 14:01
Mein Code erfüllt doch deinen zweck..
Das Format was dabei im Speicher liegt ist unwichtig.
Wichtig ist nur das mit meinem Code ein PNG zurückgegeben wird in höchster Qualität.

Dieses kannst du dann auf deine Größe zurecht stutzen.

Du benötigst nur den Pointer auf die im Speicher liegende Datei und die länge.
Ich habe das teil mal für einen Tag Editor (Coverart) geschrieben da weißt du auch nicht welches Bildformat im Tag abgelegt ist.

gruss

Geändert von EWeiss (16. Aug 2016 um 14:04 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sherlock
Sherlock

Registriert seit: 10. Jan 2006
Ort: Offenbach
3.811 Beiträge
 
Delphi 12 Athens
 
#6

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

  Alt 16. Aug 2016, 14:19
Unter Windows könntest Du TWICImage verwenden. Das kennt alle gängigen Formate und bietet Methoden zum Ändern der Größe unter Beibehaltung der Transparenz. Es ist jedoch (vermutlich weil es OS-Methoden nicht gut kapselt) nicht sonderlich schnell, wie hier gezeigt wurde. Ein Beispiel wie ein Image verkleinert wird ist hier zu finden.

Sherlock
Oliver
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann
  Mit Zitat antworten Zitat
berens

Registriert seit: 3. Sep 2004
441 Beiträge
 
Delphi 10.4 Sydney
 
#7

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

  Alt 16. Aug 2016, 14:39
Danke für die Beiträge.

Zuerst nochmal "sorry" @EWeiss, beim schreiben meiner ersten Antwort hatte ich Deinen Post nur bis "Was möchtest du also?" gesehen/gelesen und dachte ursprünglich mein erster Post wäre unklar.

Deinen Code habe ich mir angeschaut, weiß allerdings nicht so Recht, wie ich das auf Delphi übertragen soll bzw. was der Code macht. Von den Prozedurnamen her scheinst Du eine Datei zu laden, die Metadaten zu entfernen und die Datei wieder zu speichern. Den eigentlichen Transfer machst du mit DrawImage, und scheinst direkt auf eine TGraphic zu zeichnen (geht in Delphi nicht?), bzw. auf ein Bitmap (wieder Problem mit 32Bit/Alpha bzw. dem Pixelformat ansich). Dafür bin ich leider nicht gut genug in C drin, damit ich das auch nur gedanklich übertragen könnte, vll. kannst du nochmal 1-2 Kommentare zu den Zeilen machen, bitte?

Mein aktueller Lösungsweg sieht dank @bytecook so aus, dass ich den Umweg über TBitmap32 und TPortableNetworkGraphic32 gehe. Abgesehen von vielen, vielen Units die nun zusätzlich in meinem Projekt für eine Quelltextzeile mitverwendet werden müssen (jammern auf hohem Nivea ) kann ich nicht direkt von TBitmap32 in einen MemoryStream speichern, da das Format (logischerweise) anders ist als TBitmap, und somit TglBitmap2D das nicht laden kann. Also Umweg über PNG-Komponente, das geht generell, ABER: Trotz eines wirklich schnellen Rechners dauert png32.Assign bald über 10 Sekunden. Wenn der Benutzer also 10-20 Bilder einfügt, dauert das Starten vom Programm dann bald 2-3 Minuten, das kann ja dann wohl auch nicht sein.

Wo habe ich den Fehler, wie geht es anders?

@Sherlock: Ich befürchte, TPortableNetworkGraphic32 benutzt vielleicht auch WIC und ist deshalb so langsam?

Primär die Frage: Wie erzeuge ich ein leeres TPNGImage mit 32 Bit Farbtiefe incl. Alphakanal?

   png := TPngImage.CreateBlank(COLOR_RGBALPHA, 32, 2048, 1024); erzeugt:
Zitat:
---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt bla.exe ist eine Exception der Klasse EPNGInvalidSpec mit der Meldung '"Portable Network Graphics" konnte nicht erstellt werden, weil ungültige Bildtypparameter angegeben wurden.' aufgetreten.

Delphi-Quellcode:
uses
  ..., GR32, gr32_png;

var
  bmp32: TBitmap32;
  png32: TPortableNetworkGraphic32;
begin
   bmp32 := TBitmap32.Create;
   bmp32.Width := 2048; // zum testen
   bmp32.Height := 1024;
   bmp32.Canvas.Draw(0, 0, tmpImage.Picture.Graphic); // zum Testen auch keine Skalierung etc.

   png32 := TPortableNetworkGraphic32.Create;
   png32.Assign(bmp32);

   ms := TMemoryStream.Create;
   ms.Position := 0;
   png32.SaveToStream(ms);
// bmp32.SaveToStream(ms); // geht nicht, TglBitmap2D kann das dann nicht wieder einlesen
   ms.Position := 0;
   LoadFromStream(ms);
   FreeAndNil(ms);

   GenTexture(True); // geladene Textur an OpenGL übergeben

   FreeAndNil(png32);
   FreeAndNil(bmp32);
Edit:
Ich habe es nun mit WIC versucht, und es geht einfach und schnell:

Delphi-Quellcode:
var
  wic: TWICImage;
begin
ms := TMemoryStream.Create;
ms.Position := 0;
wic := TWICImage.Create;
wic.LoadFromFile(_Filename);
wic.ImageFormat := wifPng;
wic.SaveToStream(ms);
ms.Position := 0;
   LoadFromStream(ms);
   FreeAndNil(ms);

   GenTexture(True); // geladene Textur an OpenGL übergeben
Aktuell kann ich nun sowohl meine .png wie auch .bmp-Datei korrekt laden. Es ist halt nur die Frage, wie ich das nun noch ohne AlphaVerlust skaliere. Der Link zum verkleinern von TWicImage erfordert das IWICBitmapScaler aus der windowscodec.dll. Gibt es bei Delphi 2010 standardmäßig nicht. Muss ich gleich mal schauen, wie ich das Bild klein bekomme...

Geändert von berens (16. Aug 2016 um 14:54 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.343 Beiträge
 
Delphi 12 Athens
 
#8

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

  Alt 16. Aug 2016, 15:04
Wenn der Benutzer ein Bild auswählt erzeuge anhand der Dateiendung ein Objekt der entsprechenden TGraphic-Klasse (TPNGImage, TBitmap, ...).
Nja, bezüglich TImage ... joar, ist blöd, vorallem wenn nicht-visuell.

Aber man kann auch TPicture direkt verwenden.
Bei dem registrieren sich standardmäßig alle TGraphic-Klassen mit ihren Dateiendungen.
Picture.LoadFromStream geht da leider nicht, da diese Delphi-Klassen ausschließlich auf die Dateiendung achten, welche es beim Stream nicht gibt.
Picture.LoadFromFile nimmt dann anhand der Dateiendung eine der registrierten TGraphic, erstellt davon eine Instanz in Picture.Graphic und läd da rein dann das Bild.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort


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 21:27 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz