187 lines
No EOL
7.3 KiB
C#
187 lines
No EOL
7.3 KiB
C#
using AC2RE.Definitions;
|
|
|
|
namespace LandblockExtraction.Tools;
|
|
public static class DDSHeader {
|
|
//MagicNumber for DDS file.
|
|
private static readonly uint MAGICNUMBER = 0x20534444;
|
|
//Length of header
|
|
private static readonly int LENGTH = 125;
|
|
public static byte[] Generate(RenderSurface renderSurface) {
|
|
if (renderSurface.pixelFormat == PixelFormat.CUSTOM_RAW_JPEG) return renderSurface.sourceData;
|
|
|
|
DDS_HEADER header = genHeadStruct(renderSurface.pixelFormat, renderSurface.height, renderSurface.width);
|
|
using (MemoryStream stream = new MemoryStream(LENGTH + renderSurface.sourceData.Length)) {
|
|
stream.Write(BitConverter.GetBytes(MAGICNUMBER));
|
|
stream.Write(BitConverter.GetBytes(header.dwSize));
|
|
stream.Write(BitConverter.GetBytes((uint)header.dwFlags));
|
|
stream.Write(BitConverter.GetBytes(header.dwHeight));
|
|
stream.Write(BitConverter.GetBytes(header.dwWidth));
|
|
stream.Write(BitConverter.GetBytes(header.dwPitchOrLinearSize));
|
|
stream.Write(BitConverter.GetBytes(header.dwDepth));
|
|
stream.Write(BitConverter.GetBytes(header.dwMipMapCount));
|
|
foreach (var i in header.dwReserved1) stream.Write(BitConverter.GetBytes(i));
|
|
stream.Write(BitConverter.GetBytes(header.ddspf.dwSize));
|
|
stream.Write(BitConverter.GetBytes((uint)header.ddspf.dwFlags));
|
|
stream.Write(BitConverter.GetBytes(header.ddspf.dwFourCC));
|
|
stream.Write(BitConverter.GetBytes(header.ddspf.dwRGBBitCount));
|
|
stream.Write(BitConverter.GetBytes(header.ddspf.dwRBitMask));
|
|
stream.Write(BitConverter.GetBytes(header.ddspf.dwGBitMask));
|
|
stream.Write(BitConverter.GetBytes(header.ddspf.dwBBitMask));
|
|
stream.Write(BitConverter.GetBytes(header.ddspf.dwABitMask));
|
|
stream.Write(BitConverter.GetBytes(header.dwCaps));
|
|
stream.Write(BitConverter.GetBytes(header.dwCaps2));
|
|
stream.Write(BitConverter.GetBytes(header.dwCaps3));
|
|
stream.Write(BitConverter.GetBytes(header.dwCaps4));
|
|
stream.Write(BitConverter.GetBytes(header.dwReserved2));
|
|
stream.Write(renderSurface.sourceData);
|
|
|
|
return stream.ToArray();
|
|
}
|
|
}
|
|
|
|
private static DDS_HEADER genHeadStruct(PixelFormat format, uint height, uint width) {
|
|
//I think always same each format?
|
|
DDS_HEADER dDS_HEADER = new DDS_HEADER();
|
|
dDS_HEADER.dwFlags |= DDSHeaderFlags.DDSD_CAPS | DDSHeaderFlags.DDSD_HEIGHT | DDSHeaderFlags.DDSD_WIDTH | DDSHeaderFlags.DDSD_PIXELFORMAT;
|
|
|
|
if (dDS_HEADER.dwFlags.HasFlag(DDSHeaderFlags.DDSD_HEIGHT)) dDS_HEADER.dwHeight = height;
|
|
if (dDS_HEADER.dwFlags.HasFlag(DDSHeaderFlags.DDSD_WIDTH)) dDS_HEADER.dwWidth = width;
|
|
|
|
if (format == PixelFormat.DXT1) {
|
|
dDS_HEADER.dwFlags |= DDSHeaderFlags.DDSD_LINEARSIZE;
|
|
dDS_HEADER.dwPitchOrLinearSize = CalculateCompressedBlockSize(height, width, (uint)new byte[8].Length);
|
|
}
|
|
if (format == PixelFormat.DXT3 || format == PixelFormat.DXT2 || format == PixelFormat.DXT4 || format == PixelFormat.DXT5) {
|
|
dDS_HEADER.dwFlags |= DDSHeaderFlags.DDSD_LINEARSIZE;
|
|
dDS_HEADER.dwPitchOrLinearSize = CalculateCompressedBlockSize(height, width, (uint)new byte[16].Length);
|
|
}
|
|
|
|
if (dDS_HEADER.dwFlags.HasFlag(DDSHeaderFlags.DDSD_PIXELFORMAT)) dDS_HEADER.ddspf = genPixelformatStruct(format);
|
|
|
|
return dDS_HEADER;
|
|
}
|
|
|
|
private static DDS_PIXELFORMAT genPixelformatStruct(PixelFormat surface) {
|
|
DDS_PIXELFORMAT dDS_PIXELFORMAT = new DDS_PIXELFORMAT();
|
|
|
|
switch (surface) {
|
|
case PixelFormat.DXT1:
|
|
case PixelFormat.DXT3:
|
|
case PixelFormat.DXT4:
|
|
case PixelFormat.DXT5:
|
|
dDS_PIXELFORMAT.dwFlags |= DDSPixelformatFlags.DDPF_FOURCC;
|
|
dDS_PIXELFORMAT.dwFourCC = (uint)surface;
|
|
break;
|
|
case PixelFormat.A8R8G8B8:
|
|
dDS_PIXELFORMAT.dwFlags |= DDSPixelformatFlags.DDPF_ALPHAPIXELS | DDSPixelformatFlags.DDPF_RGB;
|
|
dDS_PIXELFORMAT.dwRGBBitCount = 0x20;
|
|
dDS_PIXELFORMAT.dwRBitMask = 0x00FF0000;
|
|
dDS_PIXELFORMAT.dwGBitMask = 0x0000FF00;
|
|
dDS_PIXELFORMAT.dwBBitMask = 0x000000FF;
|
|
dDS_PIXELFORMAT.dwABitMask = 0xFF000000;
|
|
break;
|
|
case PixelFormat.R8G8B8:
|
|
dDS_PIXELFORMAT.dwFlags |= DDSPixelformatFlags.DDPF_RGB;
|
|
dDS_PIXELFORMAT.dwRGBBitCount = 0x18;
|
|
dDS_PIXELFORMAT.dwRBitMask = 0x00FF0000;
|
|
dDS_PIXELFORMAT.dwGBitMask = 0x0000FF00;
|
|
dDS_PIXELFORMAT.dwBBitMask = 0x000000FF;
|
|
break;
|
|
case PixelFormat.A8:
|
|
dDS_PIXELFORMAT.dwFlags |= DDSPixelformatFlags.DDPF_ALPHAPIXELS;
|
|
dDS_PIXELFORMAT.dwRGBBitCount = 0x8;
|
|
dDS_PIXELFORMAT.dwABitMask = 0xFF;
|
|
break;
|
|
default:
|
|
dDS_PIXELFORMAT.dwFlags |= DDSPixelformatFlags.DDPF_FOURCC;
|
|
break;
|
|
}
|
|
|
|
return dDS_PIXELFORMAT;
|
|
}
|
|
public static uint CalculateCompressedBlockSize(uint height, uint width, uint blockSize) {
|
|
return ((width + 3) / 4) * ((height + 3) / 4) * blockSize;
|
|
}
|
|
}
|
|
|
|
public struct DDS_HEADER {
|
|
public uint dwSize;
|
|
public DDSHeaderFlags dwFlags;
|
|
public uint dwHeight;
|
|
public uint dwWidth;
|
|
public uint dwPitchOrLinearSize;
|
|
public uint dwDepth;
|
|
public uint dwMipMapCount;
|
|
public uint[] dwReserved1;
|
|
public DDS_PIXELFORMAT ddspf;
|
|
public uint dwCaps;
|
|
public uint dwCaps2;
|
|
public uint dwCaps3;
|
|
public uint dwCaps4;
|
|
public uint dwReserved2;
|
|
|
|
public DDS_HEADER() {
|
|
dwSize = 124; //Fixed on 124 octets
|
|
dwFlags = 0;
|
|
dwHeight = 0;
|
|
dwWidth = 0;
|
|
dwPitchOrLinearSize = 0;
|
|
dwDepth = 0;
|
|
dwMipMapCount = 0;
|
|
dwReserved1 = new uint[11];
|
|
foreach (var i in dwReserved1) dwReserved1[i] = 0x00000000;
|
|
ddspf = new DDS_PIXELFORMAT();
|
|
dwCaps = 0x1000;
|
|
dwCaps2 = 0;
|
|
dwCaps3 = 0;
|
|
dwCaps4 = 0;
|
|
dwReserved2 = 0;
|
|
|
|
|
|
}
|
|
}
|
|
public struct DDS_PIXELFORMAT {
|
|
public uint dwSize;
|
|
public DDSPixelformatFlags dwFlags;
|
|
public uint dwFourCC;
|
|
public uint dwRGBBitCount;
|
|
public uint dwRBitMask;
|
|
public uint dwGBitMask;
|
|
public uint dwBBitMask;
|
|
public uint dwABitMask;
|
|
|
|
public DDS_PIXELFORMAT() {
|
|
dwSize = 32; //Fixed on 32 octets
|
|
dwFlags = 0;
|
|
dwFourCC = 0;
|
|
dwRGBBitCount = 0;
|
|
dwRBitMask = 0;
|
|
dwGBitMask = 0;
|
|
dwBBitMask = 0;
|
|
dwABitMask = 0;
|
|
}
|
|
}
|
|
|
|
[Flags]
|
|
public enum DDSHeaderFlags : uint {
|
|
NONE = 0,
|
|
DDSD_CAPS = 1 << 0, // 0x00000001
|
|
DDSD_HEIGHT = 1 << 1, // 0x00000002
|
|
DDSD_WIDTH = 1 << 2, // 0x00000004
|
|
DDSD_PITCH = 1 << 3, // 0x00000008
|
|
DDSD_PIXELFORMAT = 1 << 12, // 0x00001000
|
|
DDSD_MIPMAPCOUNT = 1 << 17, // 0x00020000
|
|
DDSD_LINEARSIZE = 1 << 19, // 0x00080000
|
|
DDSD_DEPTH = 1 << 23, // 0x00800000
|
|
}
|
|
|
|
[Flags]
|
|
public enum DDSPixelformatFlags : uint {
|
|
NONE = 0,
|
|
DDPF_ALPHAPIXELS = 1 << 0, // 0x00000001
|
|
DDPF_ALPHA = 1 << 1, // 0x00000002
|
|
DDPF_FOURCC = 1 << 2, // 0x00000004
|
|
DDPF_RGB = 1 << 6, // 0x00000040
|
|
DDPF_YUV = 1 << 9, // 0x00000200
|
|
DDPF_LUMINANCE = 1 << 17, // 0x00020000
|
|
} |