Skip to content

Commit

Permalink
Finish initial support for other surface formats
Browse files Browse the repository at this point in the history
  • Loading branch information
iMrShadow committed Mar 21, 2024
1 parent 5cc0830 commit 069a083
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 35 deletions.
59 changes: 47 additions & 12 deletions DDS_D3DTX_Converter_GUI/DDS_D3DTX_Converter/DirectX/DDS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,17 +301,28 @@ public static DDS_HEADER GetHeaderFromBytes(byte[] byteArray)

Marshal.Copy(byteArray, 0, ptr, size);


//Initialize DDS_HEADER_DXT10
DDS_HEADER_DXT10 dxt10HeaderObject = new();
// dxt10HeaderObject.dxgiFormat = ;

headerObject = (DDS_HEADER)Marshal.PtrToStructure(ptr, headerObject.GetType());
Marshal.FreeHGlobal(ptr);

return headerObject;
}

public static DDS_HEADER_DXT10 GetDX10HeaderFromBytes(byte[] byteArray)
{
DDS_HEADER_DXT10 dxt10HeaderObject = new();

int dx10_size = Marshal.SizeOf(dxt10HeaderObject);
IntPtr dx10_ptr = Marshal.AllocHGlobal(dx10_size);

Marshal.Copy(byteArray, 0, dx10_ptr, dx10_size);

dxt10HeaderObject = (DDS_HEADER_DXT10)Marshal.PtrToStructure(dx10_ptr, dxt10HeaderObject.GetType());
Marshal.FreeHGlobal(dx10_ptr);

Console.WriteLine("DXGI FORMAT: " + dxt10HeaderObject.dxgiFormat);
return dxt10HeaderObject;
}

/// <summary>
/// Converts a DDS_HEADER object into a byte array.
/// </summary>
Expand All @@ -330,6 +341,24 @@ public static byte[] GetHeaderBytes(DDS_HEADER header)
return arr;
}

/// <summary>
/// Converts a DDS_HEADER_DXT10 object into a byte array.
/// </summary>
/// <param name="header"></param>
/// <returns></returns>
public static byte[] GetDXT10HeaderBytes(DDS_HEADER_DXT10 header)
{
int size = Marshal.SizeOf(header);
byte[] arr = new byte[size];

IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(header, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);

return arr;
}

public static DDS_HEADER GetBlankHeader()
{
return new()
Expand Down Expand Up @@ -368,6 +397,15 @@ public static DDS_HEADER GetPresetHeader()
};
}

public static DDS_HEADER_DXT10 GetPresetDXT10Header()
{
return new()
{
dxgiFormat = DXGI_FORMAT.R32G32B32_SINT,
resourceDimension = D3D10_RESOURCE_DIMENSION.D3D10_RESOURCE_DIMENSION_TEXTURE2D
};
}

public static uint Get_FourCC_FromTellale(T3SurfaceFormat format)
{
return format switch
Expand Down Expand Up @@ -433,17 +471,14 @@ public static T3SurfaceFormat Get_T3Format_FromFourCC(uint fourCC, DDS_Master dd
else if (fourCC == ByteFunctions.Convert_String_To_UInt32("ATI1")) return T3SurfaceFormat.eSurface_DXT5A;
else if (fourCC == ByteFunctions.Convert_String_To_UInt32("BC4S")) return T3SurfaceFormat.eSurface_BC4;
else if (fourCC == ByteFunctions.Convert_String_To_UInt32("BC5S")) return T3SurfaceFormat.eSurface_BC5;
else if (fourCC == ByteFunctions.Convert_String_To_UInt32("DX10")) return Parse_T3Format_FromDX10(dds.sourceFileData);
else if (fourCC == ByteFunctions.Convert_String_To_UInt32("DX10")) return Parse_T3Format_FromDX10(dds.dxt10_header.dxgiFormat);
else return T3SurfaceFormat.eSurface_DXT1;
}

public static T3SurfaceFormat Parse_T3Format_FromDX10(byte[] data)
public static T3SurfaceFormat Parse_T3Format_FromDX10(DXGI_FORMAT dxgi_format)
{
int startIndex = 128;

int dxgi_format = BitConverter.ToInt32(data, startIndex);

return dxgi_format switch
Console.WriteLine((int)dxgi_format);
return (int)dxgi_format switch
{
(int)DXGI_FORMAT.R8G8B8A8_UNORM_SRGB => T3SurfaceFormat.eSurface_ARGB8,
(int)DXGI_FORMAT.R8G8B8A8_UNORM => T3SurfaceFormat.eSurface_ARGB8,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static ImageProperties GetImagePropertiesFromD3DTX(string filePath)
return new ImageProperties()
{
Name = master.GetTextureName(),
CompressionType = master.GetCompressionType(),
CompressionType = master.GetStringCompressionType(),
Width = master.GetWidth().ToString(),
Height = master.GetHeight().ToString(),
HasAlpha = master.GetHasAlpha(),
Expand Down
20 changes: 19 additions & 1 deletion DDS_D3DTX_Converter_GUI/DDS_D3DTX_Converter/Main/D3DTX_Master.cs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ public uint GetWidth()
return 0;
}

public string GetCompressionType()
public string GetStringCompressionType()
{
if (d3dtx4 != null)
return Enum.GetName(d3dtx4.mSurfaceFormat).Remove(0, 9);
Expand All @@ -427,6 +427,24 @@ public string GetCompressionType()
return "Not Available";
}

public T3SurfaceFormat GetCompressionType()
{
if (d3dtx4 != null)
return d3dtx4.mSurfaceFormat;
else if (d3dtx5 != null)
return d3dtx5.mSurfaceFormat;
else if (d3dtx6 != null)
return d3dtx6.mSurfaceFormat;
else if (d3dtx7 != null)
return d3dtx7.mSurfaceFormat;
else if (d3dtx8 != null)
return d3dtx8.mSurfaceFormat;
else if (d3dtx9 != null)
return d3dtx9.mSurfaceFormat;
else
return T3SurfaceFormat.eSurface_Unknown;
}

public string GetChannelCount()
{
if (d3dtx4 != null)
Expand Down
33 changes: 29 additions & 4 deletions DDS_D3DTX_Converter_GUI/DDS_D3DTX_Converter/Main/DDS_Master.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using D3DTX_Converter.Utilities;
using D3DTX_Converter.DirectX;
using D3DTX_Converter.TelltaleEnums;
using DirectXTexNet;
using System.ComponentModel;

/*
* DXT1 - DXGI_FORMAT_BC1_UNORM / D3DFMT_DXT1
Expand Down Expand Up @@ -51,6 +53,8 @@ public class DDS_Master

public DDS_HEADER header;

public DDS_HEADER_DXT10 dxt10_header;

/// <summary>
/// A struct used when matching a DDS with a D3DTX.
/// </summary>
Expand Down Expand Up @@ -105,7 +109,6 @@ public DDS_Master(D3DTX_Master d3dtx)
header = DDS.GetPresetHeader();

T3SurfaceFormat surfaceFormat = T3SurfaceFormat.eSurface_DXT1;

//header.dwCaps = DDSCAPS.DDSCAPS_TEXTURE | DDSCAPS.DDSCAPS_MIPMAP;

if (d3dtx.d3dtx4 != null)
Expand Down Expand Up @@ -144,6 +147,7 @@ public DDS_Master(D3DTX_Master d3dtx)
header.dwMipMapCount = d3dtx.d3dtx8.mNumMipLevels;
header.dwDepth = d3dtx.d3dtx8.mDepth;
surfaceFormat = d3dtx.d3dtx8.mSurfaceFormat;

}
else if (d3dtx.d3dtx9 != null)
{
Expand All @@ -152,10 +156,19 @@ public DDS_Master(D3DTX_Master d3dtx)
header.dwMipMapCount = d3dtx.d3dtx9.mNumMipLevels;
header.dwDepth = d3dtx.d3dtx9.mDepth;
surfaceFormat = d3dtx.d3dtx9.mSurfaceFormat;

}

header.ddspf.dwFourCC = DDS.Get_FourCC_FromTellale(surfaceFormat);

if (header.ddspf.dwFourCC == ByteFunctions.Convert_String_To_UInt32("DX10"))
{
dxt10_header = DDS.GetPresetDXT10Header();
dxt10_header.dxgiFormat = DDS.GetSurfaceFormatAsDXGI(surfaceFormat);
dxt10_header.resourceDimension = d3dtx.IsCubeTexture() ? D3D10_RESOURCE_DIMENSION.D3D10_RESOURCE_DIMENSION_TEXTURE3D : D3D10_RESOURCE_DIMENSION.D3D10_RESOURCE_DIMENSION_TEXTURE2D;
dxt10_header.arraySize = 1; //TODO NEEDS TESTING
}

switch (surfaceFormat)
{
case T3SurfaceFormat.eSurface_A8:
Expand Down Expand Up @@ -193,21 +206,31 @@ private void GetData(byte[] fileData, bool headerOnly)
Console.WriteLine("DDS Mip Map Count = {0}", header.dwMipMapCount);
Console.WriteLine("DDS Compression = {0}", header.ddspf.dwFourCC);

//get dxt10 header if it exists
if (header.ddspf.dwFourCC == ByteFunctions.Convert_String_To_UInt32("DX10"))
{
byte[] dxt10headerBytes = ByteFunctions.AllocateBytes(20, fileData, 128); //skip the main header
dxt10_header = DDS.GetDX10HeaderFromBytes(dxt10headerBytes);
}

if (headerOnly)
return;

//--------------------------EXTRACT DDS TEXTURE DATA--------------------------
//calculate dds header length (we add 4 because we skipped the 4 bytes which contain the ddsPrefix, it isn't necessary to parse this data)
uint ddsHeaderLength = 4 + header.dwSize;

//if dxt10Header is present, add additional 20 bytes
uint dxt10HeaderLength = (uint)((header.ddspf.dwFourCC == ByteFunctions.Convert_String_To_UInt32("DX10")) ? 20 : 0);

//calculate the length of just the dds texture data
uint ddsTextureDataLength = (uint)sourceFileData.Length - ddsHeaderLength;
uint ddsTextureDataLength = (uint)sourceFileData.Length - ddsHeaderLength - dxt10HeaderLength;

//allocate a byte array of dds texture length
byte[] ddsTextureData = new byte[ddsTextureDataLength];

//copy the data from the source byte array past the header (so we are only getting texture data)
Array.Copy(sourceFileData, ddsHeaderLength, ddsTextureData, 0, ddsTextureData.Length);
Array.Copy(sourceFileData, ddsHeaderLength + dxt10HeaderLength, ddsTextureData, 0, ddsTextureData.Length);

textureData = new();

Expand Down Expand Up @@ -341,6 +364,7 @@ public void Write_D3DTX_AsDDS(D3DTX_Master d3dtx, string destinationDirectory)
{
//turn our header data into bytes to be written into a file
byte[] dds_header = ByteFunctions.Combine(ByteFunctions.GetBytes("DDS "), DDS.GetHeaderBytes(header));
dds_header = ByteFunctions.Combine(dds_header, DDS.GetDXT10HeaderBytes(dxt10_header));

//copy the dds header to the file
byte[] finalData = Array.Empty<byte>();
Expand Down Expand Up @@ -371,7 +395,7 @@ public void Match_DDS_With_D3DTX(string ddsPath, D3DTX_Master d3dtx, DDS_Matchin
{
}



public byte[] GetData(D3DTX_Master d3dtx)
{
Expand Down Expand Up @@ -410,6 +434,7 @@ public byte[] GetData(D3DTX_Master d3dtx)
{
//turn our header data into bytes to be written into a file
byte[] dds_header = ByteFunctions.Combine(ByteFunctions.GetBytes("DDS "), DDS.GetHeaderBytes(header));
dds_header = ByteFunctions.Combine(dds_header, DDS.GetDXT10HeaderBytes(dxt10_header));

//copy the dds header to the file
byte[] finalData = Array.Empty<byte>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace D3DTX_Converter.Utilities
{
public static class ImageUtilities
{

/// <summary>
/// Checks if the image from a file path is transparent.
/// </summary>
Expand Down Expand Up @@ -59,7 +59,7 @@ public static bool IsImageOpaque(string imageFilePath)
/// <returns></returns>
public static bool IsImageOpaque(Image<Rgba32> image)
{

bool hasAlpha = false;

image.ProcessPixelRows(pixelAccessor =>
Expand All @@ -86,7 +86,7 @@ public static bool IsImageOpaque(Image<Rgba32> image)

return hasAlpha;
}

/// <summary>
/// Converts .dds (and .tga) files to a bitmap. This is only used in the image preview.
/// </summary>
Expand All @@ -97,12 +97,12 @@ public static WriteableBitmap ConvertFileFromDdsToBitmap(string filePath)
{
//load the image
using var image = Pfimage.FromFile(filePath);

//get the data
var newData = image.Data;
var newDataLen = image.DataLen;
var stride = image.Stride;

//get the color type
SKColorType colorType;
switch (image.Format)
Expand Down Expand Up @@ -138,7 +138,7 @@ public static WriteableBitmap ConvertFileFromDdsToBitmap(string filePath)
default:
throw new ArgumentException($"Skia unable to interpret pfim format: {image.Format}");
}

//Converts the data into writeableBitmap. (TODO Insert a link to the code)
var imageInfo = new SKImageInfo(image.Width, image.Height, colorType);
var handle = GCHandle.Alloc(newData, GCHandleType.Pinned);
Expand Down Expand Up @@ -170,7 +170,7 @@ public static WriteableBitmap ConvertTiffToBitmap(string filePath)
// read the dimensions
var width = tifImg.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
var height = tifImg.GetField(TiffTag.IMAGELENGTH)[0].ToInt();

//Experimentation, ignore this
//var smth = tifImg.GetField(TiffTag.COMPRESSION)[0].ToInt();

Expand Down Expand Up @@ -212,7 +212,7 @@ public static WriteableBitmap ConvertTiffToBitmap(string filePath)
}

/// <summary>
/// Converts .d3dtx files to a bitmap. This is only used in the image preview.
/// Converts .d3dtx files to a bitmap (by converting to .dds first). This is only used in the image preview.
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
Expand All @@ -221,20 +221,21 @@ public static WriteableBitmap ConvertD3dtxToBitmap(string filePath)
var d3dtx = new D3DTX_Master();
d3dtx.Read_D3DTX_File(filePath);
DDS_Master ddsFile = new(d3dtx);
//implement get without header (to see)
var array = ddsFile.GetData(d3dtx);
Stream stream = new MemoryStream(array);
var image = Pfimage.FromStream(stream);

WriteableBitmap writeableBitmap = new WriteableBitmap(
new PixelSize(image.Width, image.Height),
new Vector(96, 96),
PixelFormat.Bgra8888,
AlphaFormat.Premul);
var image = Pfimage.FromStream(stream);
WriteableBitmap writeableBitmap = new WriteableBitmap(
new PixelSize(image.Width, image.Height),
new Vector(96, 96),
PixelFormat.Bgra8888,
AlphaFormat.Premul);

using var lockedBitmap = writeableBitmap.Lock();
Marshal.Copy(image.Data, 0, lockedBitmap.Address, image.DataLen);
using var lockedBitmap = writeableBitmap.Lock();
Marshal.Copy(image.Data, 0, lockedBitmap.Address, image.DataLen);

return writeableBitmap;
return writeableBitmap;
}
}
}

0 comments on commit 069a083

Please sign in to comment.