Exemplo n.º 1
0
        public static DdsFile FromFileSystemEntry(FileSystemEntry entry)
        {
            using (var stream = entry.Open())
                using (var reader = new BinaryReader(stream, Encoding.ASCII, true))
                {
                    var magic = reader.ReadUInt32();
                    if (magic.ToFourCcString() != "DDS ")
                    {
                        throw new InvalidDataException();
                    }

                    var header = DdsHeader.Parse(reader);

                    var imageFormat = GetImageFormat(header.PixelFormat.FourCc);

                    if (header.Flags.HasFlag(DdsHeaderFlags.Depth) ||
                        header.Caps2.HasFlag(DdsCaps2.CubeMap) ||
                        header.Caps2.HasFlag(DdsCaps2.Volume))
                    {
                        throw new NotSupportedException();
                    }

                    var mipMapCount = header.MipMapCount;
                    var mipMaps     = new DdsMipMap[mipMapCount];

                    var width  = header.Width;
                    var height = header.Height;
                    for (var i = 0; i < mipMapCount; i++)
                    {
                        var surfaceInfo = GetSurfaceInfo(width, height, imageFormat);

                        var mipMapData = reader.ReadBytes((int)surfaceInfo.NumBytes);

                        mipMaps[i] = new DdsMipMap(mipMapData, surfaceInfo.RowBytes);

                        width  >>= 1;
                        height >>= 1;

                        width  = Math.Max(width, 1);
                        height = Math.Max(height, 1);
                    }

                    return(new DdsFile
                    {
                        Header = header,
                        ImageFormat = imageFormat,
                        MipMaps = mipMaps
                    });
                }
        }
Exemplo n.º 2
0
        public static DdsFile FromStream(Stream stream)
        {
            using (var reader = new BinaryReader(stream, Encoding.ASCII, true))
            {
                var magic = reader.ReadFourCc();
                if (magic != "DDS ")
                {
                    throw new InvalidDataException();
                }

                var header = DdsHeader.Parse(reader);

                DdsImageFormat imageFormat;
                if (header.PixelFormat.Flags.HasFlag(DdsPixelFormatFlags.FourCc))
                {
                    imageFormat = GetImageFormat(header.PixelFormat.FourCc);
                }
                else if (header.PixelFormat.Flags.HasFlag(DdsPixelFormatFlags.BumpDuDv))
                {
                    imageFormat = DdsImageFormat.Rg8SNorm;
                }
                else if (header.PixelFormat.Flags.HasFlag(DdsPixelFormatFlags.Rgb))
                {
                    imageFormat = DdsImageFormat.Rgba8;
                }
                else
                {
                    throw new InvalidDataException();
                }

                var dimension = DdsTextureDimension.Texture2D;
                var arraySize = 1u;
                if (header.Flags.HasFlag(DdsHeaderFlags.Depth) && header.Caps2.HasFlag(DdsCaps2.Volume))
                {
                    dimension = DdsTextureDimension.Texture3D;
                }
                else if (header.Caps2.HasFlag(DdsCaps2.CubeMap))
                {
                    dimension = DdsTextureDimension.TextureCube;
                    if (!header.Caps2.HasFlag(DdsCaps2.AllCubeMapFaces))
                    {
                        throw new InvalidDataException();
                    }
                    arraySize = 6;
                }

                var isCompressed = imageFormat == DdsImageFormat.Bc1 ||
                                   imageFormat == DdsImageFormat.Bc2 ||
                                   imageFormat == DdsImageFormat.Bc3;

                var mipMapCount = header.MipMapCount;
                if (mipMapCount == 0)
                {
                    mipMapCount = 1;
                }

                var mipMaps = new TextureMipMapData[mipMapCount * arraySize];

                for (var arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
                {
                    var width  = header.Width;
                    var height = header.Height;

                    if (isCompressed)
                    {
                        // Ensure width and height are multiple of 4.
                        width  = (width + 3) / 4 * 4;
                        height = (height + 3) / 4 * 4;
                    }

                    var depth = Math.Max(header.Depth, 1);

                    for (var i = 0; i < mipMapCount; i++)
                    {
                        var surfaceInfo = GetSurfaceInfo(width, height, imageFormat, header);

                        var numSurfaceBytes = surfaceInfo.NumBytes * depth;
                        var mipMapData      = reader.ReadBytes((int)numSurfaceBytes);
                        if (mipMapData.Length != numSurfaceBytes)
                        {
                            throw new InvalidDataException();
                        }

                        // Set alpha bytes for 32-bit rgb images that don't include alpha data.
                        if (imageFormat == DdsImageFormat.Rgba8 && !header.PixelFormat.Flags.HasFlag(DdsPixelFormatFlags.AlphaPixels))
                        {
                            for (var j = 0; j < mipMapData.Length; j += 4)
                            {
                                mipMapData[j + 3] = 255;
                            }
                        }

                        mipMaps[(arrayIndex * mipMapCount) + i] = new TextureMipMapData(
                            mipMapData,
                            surfaceInfo.RowBytes,
                            surfaceInfo.NumBytes,
                            width,
                            height);

                        width  >>= 1;
                        height >>= 1;
                        depth  >>= 1;

                        if (isCompressed)
                        {
                            // Round width and height down to multiple of 4.
                            width  -= width % 4;
                            height -= height % 4;

                            width  = Math.Max(width, 4);
                            height = Math.Max(height, 4);
                        }
                        else
                        {
                            width  = Math.Max(width, 1);
                            height = Math.Max(height, 1);
                        }

                        depth = Math.Max(depth, 1);
                    }
                }

                return(new DdsFile
                {
                    Header = header,
                    Dimension = dimension,
                    ImageFormat = imageFormat,
                    ArraySize = arraySize,
                    MipMapCount = mipMapCount,
                    MipMaps = mipMaps
                });
            }
        }