Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Anzeigen von DDS Dateien (https://www.delphipraxis.net/194484-anzeigen-von-dds-dateien.html)

creehawk 28. Nov 2017 16:34

Anzeigen von DDS Dateien
 
Moin Moin.

Ich möchte (muss) für ein Programm Grafik(Textur) Dateien vom Typ DDS anzeigen. Mit D7 kein Problem.

Mit Delphi 10.2 schon, weil alle angebotenen Hilfsmittel wie Devil, Vampyre, Andorra, glBitmap und weiß ich was in Delphi 10.2 nicht laufen, zumeist gibt es massig Typprobleme. Liegt wohl daran das die aktuellsten Ausgaben der genannten so um das Jahr 2009 datieren - aber auch Modelle aus 2015 gehen nicht.

Gibt es irgendwas Neueres, eine andere Möglichkeit?

creehawk

TiGü 28. Nov 2017 16:48

AW: Anzeigen von DDS Dateien
 
Da wirst du um das Laden per Stream und dann händisch auseinander basteln wohl nicht drum rum kommen.
Außer natürlich, jemand hat noch irgendwo eine fertige Unit parat.

Bist du mit dem Programm ILSpy und Paint.Net vertraut?
Mit dem Ersten kannst du im Zweiten nachschauen, wie im Namespace PaintDotNet.Data.Dds -> DdsFile diese Texturen geladen werden.

Beispiel:
Code:
      public void Load(Stream input)
      {
         uint ddsTag = (uint)input.ReadUInt32();
         if (ddsTag != 542327876u)
         {
            throw new FormatException("File does not appear to be a DDS image");
         }
         this.m_header.Read(input);
         if (this.m_header.m_pixelFormat.m_flags == 0u || (this.m_header.m_pixelFormat.m_flags & 4u) != 0u)
         {
            uint fourCC = this.m_header.m_pixelFormat.m_fourCC;
            int squishFlags;
            if (fourCC != 827611204u)
            {
               if (fourCC != 861165636u)
               {
                  if (fourCC != 894720068u)
                  {
                     throw new FormatException("File is not a supported DDS format");
                  }
                  squishFlags = 4;
               }
               else
               {
                  squishFlags = 2;
               }
            }
            else
            {
               squishFlags = 1;
            }
            int blockCount = (this.GetWidth() + 3) / 4 * ((this.GetHeight() + 3) / 4);
            int blockSize = ((squishFlags & 1) != 0) ? 8 : 16;
            byte[] compressedBlocks = new byte[blockCount * blockSize];
            input.Read(compressedBlocks, 0, compressedBlocks.GetLength(0));
            this.m_pixelData = DdsSquish.DecompressImage(compressedBlocks, this.GetWidth(), this.GetHeight(), squishFlags);
            return;
         }
         DdsFileFormat fileFormat;
         if (this.m_header.m_pixelFormat.m_flags == 65u && this.m_header.m_pixelFormat.m_rgbBitCount == 32u && this.m_header.m_pixelFormat.m_rBitMask == 16711680u && this.m_header.m_pixelFormat.m_gBitMask == 65280u && this.m_header.m_pixelFormat.m_bBitMask == 255u && this.m_header.m_pixelFormat.m_aBitMask == 4278190080u)
         {
            fileFormat = DdsFileFormat.DDS_FORMAT_A8R8G8B8;
         }
         else if (this.m_header.m_pixelFormat.m_flags == 64u && this.m_header.m_pixelFormat.m_rgbBitCount == 32u && this.m_header.m_pixelFormat.m_rBitMask == 16711680u && this.m_header.m_pixelFormat.m_gBitMask == 65280u && this.m_header.m_pixelFormat.m_bBitMask == 255u && this.m_header.m_pixelFormat.m_aBitMask == 0u)
         {
            fileFormat = DdsFileFormat.DDS_FORMAT_X8R8G8B8;
         }
         else if (this.m_header.m_pixelFormat.m_flags == 65u && this.m_header.m_pixelFormat.m_rgbBitCount == 32u && this.m_header.m_pixelFormat.m_rBitMask == 255u && this.m_header.m_pixelFormat.m_gBitMask == 65280u && this.m_header.m_pixelFormat.m_bBitMask == 16711680u && this.m_header.m_pixelFormat.m_aBitMask == 4278190080u)
         {
            fileFormat = DdsFileFormat.DDS_FORMAT_A8B8G8R8;
         }
         else if (this.m_header.m_pixelFormat.m_flags == 64u && this.m_header.m_pixelFormat.m_rgbBitCount == 32u && this.m_header.m_pixelFormat.m_rBitMask == 255u && this.m_header.m_pixelFormat.m_gBitMask == 65280u && this.m_header.m_pixelFormat.m_bBitMask == 16711680u && this.m_header.m_pixelFormat.m_aBitMask == 0u)
         {
            fileFormat = DdsFileFormat.DDS_FORMAT_X8B8G8R8;
         }
         else if (this.m_header.m_pixelFormat.m_flags == 65u && this.m_header.m_pixelFormat.m_rgbBitCount == 16u && this.m_header.m_pixelFormat.m_rBitMask == 31744u && this.m_header.m_pixelFormat.m_gBitMask == 992u && this.m_header.m_pixelFormat.m_bBitMask == 31u && this.m_header.m_pixelFormat.m_aBitMask == 32768u)
         {
            fileFormat = DdsFileFormat.DDS_FORMAT_A1R5G5B5;
         }
         else if (this.m_header.m_pixelFormat.m_flags == 65u && this.m_header.m_pixelFormat.m_rgbBitCount == 16u && this.m_header.m_pixelFormat.m_rBitMask == 3840u && this.m_header.m_pixelFormat.m_gBitMask == 240u && this.m_header.m_pixelFormat.m_bBitMask == 15u && this.m_header.m_pixelFormat.m_aBitMask == 61440u)
         {
            fileFormat = DdsFileFormat.DDS_FORMAT_A4R4G4B4;
         }
         else if (this.m_header.m_pixelFormat.m_flags == 64u && this.m_header.m_pixelFormat.m_rgbBitCount == 24u && this.m_header.m_pixelFormat.m_rBitMask == 16711680u && this.m_header.m_pixelFormat.m_gBitMask == 65280u && this.m_header.m_pixelFormat.m_bBitMask == 255u && this.m_header.m_pixelFormat.m_aBitMask == 0u)
         {
            fileFormat = DdsFileFormat.DDS_FORMAT_R8G8B8;
         }
         else
         {
            if (this.m_header.m_pixelFormat.m_flags != 64u || this.m_header.m_pixelFormat.m_rgbBitCount != 16u || this.m_header.m_pixelFormat.m_rBitMask != 63488u || this.m_header.m_pixelFormat.m_gBitMask != 2016u || this.m_header.m_pixelFormat.m_bBitMask != 31u || this.m_header.m_pixelFormat.m_aBitMask != 0u)
            {
               throw new FormatException("File is not a supported DDS format");
            }
            fileFormat = DdsFileFormat.DDS_FORMAT_R5G6B5;
         }
         int srcPixelSize = (int)(this.m_header.m_pixelFormat.m_rgbBitCount / 8u);
         int rowPitch;
         if ((this.m_header.m_headerFlags & 8u) != 0u)
         {
            rowPitch = (int)this.m_header.m_pitchOrLinearSize;
         }
         else if ((this.m_header.m_headerFlags & 524288u) != 0u)
         {
            rowPitch = (int)(this.m_header.m_pitchOrLinearSize / this.m_header.m_height);
         }
         else
         {
            rowPitch = (int)(this.m_header.m_width * (uint)srcPixelSize);
         }
         byte[] readPixelData = new byte[(long)rowPitch * (long)((ulong)this.m_header.m_height)];
         input.Read(readPixelData, 0, readPixelData.GetLength(0));
         this.m_pixelData = new byte[this.m_header.m_width * this.m_header.m_height * 4u];
         for (int destY = 0; destY < (int)this.m_header.m_height; destY++)
         {
            for (int destX = 0; destX < (int)this.m_header.m_width; destX++)
            {
               int srcPixelOffset = destY * rowPitch + destX * srcPixelSize;
               uint pixelColour = 0u;
               uint pixelRed = 0u;
               uint pixelGreen = 0u;
               uint pixelBlue = 0u;
               uint pixelAlpha = 0u;
               for (int loop = 0; loop < srcPixelSize; loop++)
               {
                  pixelColour |= (uint)((uint)readPixelData[srcPixelOffset + loop] << 8 * loop);
               }
               if (fileFormat == DdsFileFormat.DDS_FORMAT_A8R8G8B8)
               {
                  pixelAlpha = (pixelColour >> 24 & 255u);
                  pixelRed = (pixelColour >> 16 & 255u);
                  pixelGreen = (pixelColour >> 8 & 255u);
                  pixelBlue = (pixelColour & 255u);
               }
               else if (fileFormat == DdsFileFormat.DDS_FORMAT_X8R8G8B8)
               {
                  pixelAlpha = 255u;
                  pixelRed = (pixelColour >> 16 & 255u);
                  pixelGreen = (pixelColour >> 8 & 255u);
                  pixelBlue = (pixelColour & 255u);
               }
               else if (fileFormat == DdsFileFormat.DDS_FORMAT_A8B8G8R8)
               {
                  pixelAlpha = (pixelColour >> 24 & 255u);
                  pixelRed = (pixelColour & 255u);
                  pixelGreen = (pixelColour >> 8 & 255u);
                  pixelBlue = (pixelColour >> 16 & 255u);
               }
               else if (fileFormat == DdsFileFormat.DDS_FORMAT_X8B8G8R8)
               {
                  pixelAlpha = 255u;
                  pixelRed = (pixelColour & 255u);
                  pixelGreen = (pixelColour >> 8 & 255u);
                  pixelBlue = (pixelColour >> 16 & 255u);
               }
               else if (fileFormat == DdsFileFormat.DDS_FORMAT_A1R5G5B5)
               {
                  pixelAlpha = (pixelColour >> 15) * 255u;
                  pixelRed = (pixelColour >> 10 & 31u);
                  pixelGreen = (pixelColour >> 5 & 31u);
                  pixelBlue = (pixelColour & 31u);
                  pixelRed = (pixelRed << 3 | pixelRed >> 2);
                  pixelGreen = (pixelGreen << 3 | pixelGreen >> 2);
                  pixelBlue = (pixelBlue << 3 | pixelBlue >> 2);
               }
               else if (fileFormat == DdsFileFormat.DDS_FORMAT_A4R4G4B4)
               {
                  pixelAlpha = (pixelColour >> 12 & 255u);
                  pixelRed = (pixelColour >> 8 & 15u);
                  pixelGreen = (pixelColour >> 4 & 15u);
                  pixelBlue = (pixelColour & 15u);
                  pixelAlpha = (pixelAlpha << 4 | pixelAlpha);
                  pixelRed = (pixelRed << 4 | pixelRed);
                  pixelGreen = (pixelGreen << 4 | pixelGreen);
                  pixelBlue = (pixelBlue << 4 | pixelBlue);
               }
               else if (fileFormat == DdsFileFormat.DDS_FORMAT_R8G8B8)
               {
                  pixelAlpha = 255u;
                  pixelRed = (pixelColour >> 16 & 255u);
                  pixelGreen = (pixelColour >> 8 & 255u);
                  pixelBlue = (pixelColour & 255u);
               }
               else if (fileFormat == DdsFileFormat.DDS_FORMAT_R5G6B5)
               {
                  pixelAlpha = 255u;
                  pixelRed = (pixelColour >> 11 & 31u);
                  pixelGreen = (pixelColour >> 5 & 63u);
                  pixelBlue = (pixelColour & 31u);
                  pixelRed = (pixelRed << 3 | pixelRed >> 2);
                  pixelGreen = (pixelGreen << 2 | pixelGreen >> 4);
                  pixelBlue = (pixelBlue << 3 | pixelBlue >> 2);
               }
               int destPixelOffset = destY * (int)this.m_header.m_width * 4 + destX * 4;
               this.m_pixelData[destPixelOffset] = (byte)pixelRed;
               this.m_pixelData[destPixelOffset + 1] = (byte)pixelGreen;
               this.m_pixelData[destPixelOffset + 2] = (byte)pixelBlue;
               this.m_pixelData[destPixelOffset + 3] = (byte)pixelAlpha;
            }
         }
      }

creehawk 28. Nov 2017 17:12

AW: Anzeigen von DDS Dateien
 
Selber basteln......

Hab' ich schon geahnt. Schaun' mer ma.

Vielen Dank für die Antwort.

Creehawk

Jens01 28. Nov 2017 17:14

AW: Anzeigen von DDS Dateien
 
Hast Du wirklich die "aktuelle" Datei von glBitmap?
http://git.delphigl.com/?p=glBitmap..../master;sf=tgz
Forum https://delphigl.com/forum/viewtopic.php?p=62127#p62127

Was geht denn da nicht?

Vielleicht auch mal Herrn Bergmann fragen, der verwaltet das gerade.
http://www.delphigl.com/forum/viewtopic.php?t=7457
https://bergmann89.de/de/

Jens01 28. Nov 2017 17:19

AW: Anzeigen von DDS Dateien
 
in der "glBitmapConf.default.inc" müssen Kompilerdirektiven für Delphi eingestellt werden!

creehawk 29. Nov 2017 07:30

AW: Anzeigen von DDS Dateien
 
Moin Moin.

glBitmap habe ich samt Zubehör installiert. Mangels Dokumentation habe ich folgendes ausprobiert:


Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  TGLBMPTyp:Tglbitmapdata;
  BMPTyp:TBitmap;
begin
   BMPTyp := TBitmap.Create; TGLBMPTyp := Tglbitmapdata.Create;
   TGLBMPTyp.LoadFromFile('E:\Games\maps\Attuwe_Color.dds');
   // TGLBMPTyp.AssignToBitmap(BitmapTyp);
   TGLBMPTyp.AssignToBitmap(Form1.Image1.Picture.Bitmap);
end;

// Fehlermeldung aus UNIT GLBitmap : "Fehlerhafters Pixelformat"


procedure TForm1.Button2Click(Sender: TObject);
var
  TGLBMPTyp:Tglbitmapdata;
begin
   TGLBMPTyp := tglbitmapdata.Create;
   TGLBMPTyp.LoadFromFile('E:\Games\maps\Attuwe_Color.dds');
   TGLBMPTyp.SaveToFile('E:\Games\maps\Attuwe_Color.bmp',ftbmp);
end;

// Fehlermeldung aus UNIT GLBitmap : Unsupported Format : tf23tcDtx1rgba
Letzteres - die Formatdefinition - steht auch nicht in der Liste der unterstützten Formate. Geht also wohl nicht, es sei denn ich mache etwas falsch.

Blöderweise ist das Programm das ich da erarbeite eigentlich eine Übertragung von Delphi7 nach Delphi 10.2. Die Delphi 7 Variante arbeitet problemlos.

In Delphi7 wird die DevIL Variante verwendet (2005), die, kompiliert mit Delphi 10.2, auch problemlos arbeitet, aber nichts anzeigt. Die DevIL Variante in neuerer Version wurde überarbeitet, aber ohne Dokumentation - jedenfalls habe ich keine gefunden - veröffentlicht. Die Befehle der Version 2005 funktionieren nicht mehr.

Wat mach' ich nu?

creehawk

Redeemer 29. Nov 2017 07:57

AW: Anzeigen von DDS Dateien
 
Liste der Anhänge anzeigen (Anzahl: 1)
Lag hier rum, ist von 2012 aber sollte immer noch laufen. Methoden sind LoadDXT1, LoadDXT3 und LoadDXT5, such dir eins aus oder schreib eine Methode, das das erkennt. Index, Heights und Widths sind wegen des Programms, das sie verwendet hat, da, weil es die als vertikale ImageStrips benutzt hat und so ein wahlfreier Zugriff möglich ist. Daten werden in einen MemoryStream kopiert, weil das byteweise Lesen von FileStreams sehr langsam ist.

TiGü 29. Nov 2017 08:51

AW: Anzeigen von DDS Dateien
 
Zitat:

Zitat von Redeemer (Beitrag 1387440)
Lag hier rum, ist von 2012 aber sollte immer noch laufen. Methoden sind LoadDXT1, LoadDXT3 und LoadDXT5, such dir eins aus oder schreib eine Methode, das das erkennt. Index, Heights und Widths sind wegen des Programms, das sie verwendet hat, da, weil es die als vertikale ImageStrips benutzt hat und so ein wahlfreier Zugriff möglich ist. Daten werden in einen MemoryStream kopiert, weil das byteweise Lesen von FileStreams sehr langsam ist.

Funktioniert gut für die drei Formatvarianten (nachdem ich den Filestream-Parameter angepasst habe)!
Mit der Vorlage sollte der TE ggf. auch die anderen Formate implementieren können, wenn er sie denn braucht.

Jens01 29. Nov 2017 11:41

AW: Anzeigen von DDS Dateien
 
@creehawk
Dann würde ich sagen, glBitmap macht Dein Format nicht ....

TiGü 29. Nov 2017 13:20

AW: Anzeigen von DDS Dateien
 
Mir ist noch was eingefallen. Du könntest es auch per DirectX an sich laden.
Mit folgenden Codeschnipsel hast du zumindest die geladene DDS-Datei als IDirect3DTexture9 und IDirect3DSurface9 vorliegen.

Es würde noch die Möglichkeit geben das in eine IDirectDrawSurface7 umzukopieren und die dann wiederum zu verwenden, um ein Winapi.GDIOBJ.TGPBitmap zu erzeugen. Vom TGPBitmap aus kann man ja weitermachen...
Sag Bescheid, wenn du das dann brauchst.

Delphi-Quellcode:
uses
  Winapi.GDIPOBJ,
  Winapi.Windows,
  Winapi.Direct3D9,
  // Winapi.DirectDraw,
  Winapi.D3DX9;

procedure LoadPerDirectX(const Filename: string);
var
  HR: HRESULT;
  Direct3D: IDirect3D9Ex;
  Device: IDirect3DDevice9;
  Texture: IDirect3DTexture9;
  Params: TD3DPresentParameters;
  DisplayMode: TD3DDisplayMode;
  D3DSurface: IDirect3DSurface9;
  // DDSurface: IDirectDrawSurface7;
begin
  HR := Direct3DCreate9Ex(D3D_SDK_VERSION, Direct3D);
  if Failed(HR) then
    Exit;

  HR := Direct3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT, DisplayMode);
  if Failed(HR) then
    Exit;

  FillChar(Params, SizeOf(Params), 0);
  Params.SwapEffect := D3DSWAPEFFECT_DISCARD;
  Params.BackBufferCount := 1;
  Params.BackBufferWidth := DisplayMode.Width;
  Params.BackBufferHeight := DisplayMode.Height;
  Params.BackBufferFormat := DisplayMode.Format;

  HR := Direct3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 0, D3DCREATE_SOFTWARE_VERTEXPROCESSING, @Params, Device);
  if Failed(HR) then
    Exit;

  HR := Winapi.D3DX9.D3DXCreateTextureFromFile(Device, PWideChar(Filename), Texture);
  if Failed(HR) then
    Exit;

  HR := Texture.GetSurfaceLevel(0, D3DSurface);
  if Failed(HR) then
    Exit;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:37 Uhr.
Seite 1 von 2  1 2      

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