public static void GetSurfaceInfo(int width, int height, DdsFormat format, out int outNumBytes, out int outRowBytes, out int outNumRows) { bool bc = false; bool packed = false; bool planar = false; int bpe = 0; switch (format) { case DdsFormat.BC1Typeless: case DdsFormat.BC1UNorm: case DdsFormat.BC1UNormSrgb: case DdsFormat.BC4Typeless: case DdsFormat.BC4UNorm: case DdsFormat.BC4SNorm: bc = true; bpe = 8; break; case DdsFormat.BC2Typeless: case DdsFormat.BC2UNorm: case DdsFormat.BC2UNormSrgb: case DdsFormat.BC3Typeless: case DdsFormat.BC3UNorm: case DdsFormat.BC3UNormSrgb: case DdsFormat.BC5Typeless: case DdsFormat.BC5UNorm: case DdsFormat.BC5SNorm: case DdsFormat.BC6HalfTypeless: case DdsFormat.BC6HalfUF16: case DdsFormat.BC6HalfSF16: case DdsFormat.BC7Typeless: case DdsFormat.BC7UNorm: case DdsFormat.BC7UNormSrgb: bc = true; bpe = 16; break; case DdsFormat.R8G8B8G8UNorm: case DdsFormat.G8R8G8B8UNorm: case DdsFormat.Yuy2: packed = true; bpe = 4; break; case DdsFormat.Y210: case DdsFormat.Y216: packed = true; bpe = 8; break; case DdsFormat.NV12: case DdsFormat.P420Opaque: planar = true; bpe = 2; break; case DdsFormat.P010: case DdsFormat.P016: planar = true; bpe = 4; break; } int rowBytes; int numRows; int numBytes; if (bc) { int numBlocksWide = 0; if (width > 0) { numBlocksWide = Math.Max(1, (width + 3) / 4); } int numBlocksHigh = 0; if (height > 0) { numBlocksHigh = Math.Max(1, (height + 3) / 4); } rowBytes = numBlocksWide * bpe; numRows = numBlocksHigh; numBytes = rowBytes * numBlocksHigh; } else if (packed) { rowBytes = ((width + 1) >> 1) * bpe; numRows = height; numBytes = rowBytes * height; } else if (format == DdsFormat.NV11) { rowBytes = ((width + 3) >> 2) * 4; numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data numBytes = rowBytes * numRows; } else if (planar) { rowBytes = ((width + 1) >> 1) * bpe; numBytes = (rowBytes * height) + ((rowBytes * height + 1) >> 1); numRows = height + ((height + 1) >> 1); } else { int bpp = DdsHelpers.GetBitsPerPixel(format); rowBytes = (width * bpp + 7) / 8; // round up to nearest byte numRows = height; numBytes = rowBytes * height; } outNumBytes = numBytes; outRowBytes = rowBytes; outNumRows = numRows; }
public static DdsFile FromStream(Stream stream) { DdsFile dds = new DdsFile(); BinaryReader file = new BinaryReader(stream); int magic = file.ReadInt32(); if (magic != DdsFile.DdsMagic) { throw new InvalidDataException(); } if (file.ReadInt32() != 124) { throw new InvalidDataException(); } dds.Options = (DdsOptions)file.ReadInt32(); dds.Height = file.ReadInt32(); dds.Width = file.ReadInt32(); dds.LinearSize = file.ReadInt32(); dds.Depth = file.ReadInt32(); dds.MipmapCount = file.ReadInt32(); file.BaseStream.Position += 44; if (file.ReadInt32() != 32) { throw new InvalidDataException(); } dds.PixelFormat.Options = (DdsPixelFormatOptions)file.ReadInt32(); dds.PixelFormat.FourCC = (DdsFourCC)file.ReadInt32(); dds.PixelFormat.RgbBitCount = file.ReadInt32(); dds.PixelFormat.RedBitMask = file.ReadUInt32(); dds.PixelFormat.GreenBitMask = file.ReadUInt32(); dds.PixelFormat.BlueBitMask = file.ReadUInt32(); dds.PixelFormat.AlphaBitMask = file.ReadUInt32(); dds.Caps = (DdsCaps)file.ReadInt32(); dds.Caps2 = (DdsAdditionalCaps)file.ReadInt32(); file.BaseStream.Position += 12; if ((dds.PixelFormat.Options & DdsPixelFormatOptions.FourCC) != 0 && dds.PixelFormat.FourCC == DdsFourCC.DX10) { dds.Format = (DdsFormat)file.ReadInt32(); dds.ResourceDimension = (DdsResourceDimension)file.ReadInt32(); dds.ResourceMiscOptions = (DdsResourceMiscOptions)file.ReadInt32(); dds.ArraySize = file.ReadInt32(); DdsAlphaMode mode = (DdsAlphaMode)(file.ReadInt32() & 0x7); switch (mode) { case DdsAlphaMode.Straight: case DdsAlphaMode.Premultiplied: case DdsAlphaMode.Opaque: case DdsAlphaMode.Custom: dds.AlphaMode = mode; break; } } else { dds.Format = DdsHelpers.GetDdsFormat(dds.PixelFormat); if ((dds.PixelFormat.Options & DdsPixelFormatOptions.FourCC) != 0) { switch (dds.PixelFormat.FourCC) { case DdsFourCC.DXT2: case DdsFourCC.DXT4: dds.AlphaMode = DdsAlphaMode.Premultiplied; break; } } } dds.DataOffset = (int)file.BaseStream.Position; dds.Data = file.ReadBytes((int)file.BaseStream.Length - (int)file.BaseStream.Position); return(dds); }