public static bool Save(DDSImage Image, string Filename, CompressionMode Format) { try { return Save(Image.Images[0], Filename, Format); } catch { return false; } }
public static bool Save(DDSImage Image, Stream Stream, CompressionMode Format) { try { return Save(Image.Images[0], Stream, Format); } catch { return false; } }
public static DDSImage Load(Stream Source) { DDSImage _dds = new DDSImage(); using (BinaryReader _data = new BinaryReader(Source)) { if (_data.ReadInt32() != DDSImage.MAGIC_NUMBER) { throw new FileFormatException("DDSImage.Load() requires a .dds texture file stream"); } _dds.Format = CompressionMode.Unknown; _dds.Header.dwSize = _data.ReadInt32(); _dds.Header.dwFlags = _data.ReadInt32(); _dds.Header.dwHeight = _data.ReadInt32(); _dds.Header.dwWidth = _data.ReadInt32(); _dds.Header.dwPitchOrLinearSize = _data.ReadInt32(); _dds.Header.dwDepth = _data.ReadInt32(); _dds.Header.dwMipMapCount = _data.ReadInt32(); // Unused Reserved1 Fields _data.ReadBytes(11 * sizeof(int)); // Image Pixel Format _dds.PixelFormat.dwSize = _data.ReadUInt32(); _dds.PixelFormat.dwFlags = _data.ReadUInt32(); _dds.PixelFormat.dwFourCC = _data.ReadUInt32(); _dds.PixelFormat.dwRGBBitCount = _data.ReadUInt32(); _dds.PixelFormat.dwRBitMask = _data.ReadUInt32(); _dds.PixelFormat.dwGBitMask = _data.ReadUInt32(); _dds.PixelFormat.dwBBitMask = _data.ReadUInt32(); _dds.PixelFormat.dwABitMask = _data.ReadUInt32(); _dds.Header.dwCaps = _data.ReadInt32(); _dds.Header.dwCaps2 = _data.ReadInt32(); _dds.Header.dwCaps3 = _data.ReadInt32(); _dds.Header.dwCaps4 = _data.ReadInt32(); _dds.Header.dwReserved2 = _data.ReadInt32(); if ((_dds.PixelFormat.dwFlags & DDPF_FOURCC) != 0) { switch (_dds.PixelFormat.dwFourCC) { case FOURCC_DX10: _dds.Format = CompressionMode.DX10; throw new System.IO.FileFormatException("DX10 textures not supported at this time."); case FOURCC_DXT1: _dds.Format = CompressionMode.DXT1; break; case FOURCC_DXT2: _dds.Format = CompressionMode.DXT2; break; case FOURCC_DXT3: _dds.Format = CompressionMode.DXT3; break; case FOURCC_DXT4: _dds.Format = CompressionMode.DXT4; break; case FOURCC_DXT5: _dds.Format = CompressionMode.DXT5; break; default: switch (_dds.PixelFormat.dwFourCC) { default: break; } throw new System.IO.FileFormatException("Unsupported compression format"); } } if ((_dds.PixelFormat.dwFlags & DDPF_FOURCC) == 0) { // Uncompressed. How many BPP? bool _supportedBpp = false; switch (_dds.PixelFormat.dwRGBBitCount) { case 16: if (_dds.PixelFormat.dwABitMask == 0) { _dds.Format = CompressionMode.R5G6B5; } else { _dds.Format = CompressionMode.A1R5G5B5; } _supportedBpp = true; break; case 24: _dds.Format = CompressionMode.RGB24; _supportedBpp = true; break; case 32: _dds.Format = CompressionMode.RGB32; _supportedBpp = true; break; } if (!_supportedBpp) { throw new Exception("Only 16, 24, and 32-bit pixel formats are supported for uncompressed textures."); } } _dds.MipMapCount = 1; if ((_dds.Header.dwFlags & DDSD_MIPMAPCOUNT) != 0) { _dds.MipMapCount = (_dds.Header.dwMipMapCount == 0) ? 1 : _dds.Header.dwMipMapCount; } _dds.Images = new Bitmap[_dds.MipMapCount]; int _imageSize; int _w = (_dds.Header.dwWidth < 0) ? -_dds.Header.dwWidth : _dds.Header.dwWidth; int _h = (_dds.Header.dwHeight < 0) ? -_dds.Header.dwHeight : _dds.Header.dwHeight; // DDS Documentation recommends ignoring the dwLinearOrPitchSize value and calculating on your own. if ((_dds.PixelFormat.dwFlags & DDPF_RGB) != 0) { // Linear Size _imageSize = (_w * _h * ((int)_dds.PixelFormat.dwRGBBitCount + 7) >> 3); } else { // Compressed _imageSize = ((_w + 3) >> 2) * (((_h + 3) >> 2)); switch (_dds.PixelFormat.dwFourCC) { case FOURCC_DXT1: _imageSize <<= 3; // 64 bits color per block break; case FOURCC_DXT2: case FOURCC_DXT3: _imageSize <<= 4; // 64 bits alpha + 64 bits color per block break; case FOURCC_DXT4: case FOURCC_DXT5: _imageSize <<= 4; // 64 bits alpha + 64 bits color per block break; } } byte[] _imageBits; for (int _level = 0; _level < _dds.MipMapCount; _level++) { try { _imageBits = _data.ReadBytes(_imageSize >> (_level << 1)); int _w2 = _w >> _level; int _h2 = _h >> _level; uint _compressionMode = _dds.PixelFormat.dwFourCC; if ((_dds.PixelFormat.dwFlags & DDPF_RGB) != 0) { _compressionMode = (uint)_dds.Format; } else if ((_dds.PixelFormat.dwFlags & DDPF_FOURCC) == 0 && _dds.PixelFormat.dwRGBBitCount == 16 && _dds.PixelFormat.dwRBitMask == 0x00FF && _dds.PixelFormat.dwGBitMask == 0xFF00 && _dds.PixelFormat.dwBBitMask == 0x0000 && _dds.PixelFormat.dwABitMask == 0x0000) { _dds.Format = CompressionMode.V8U8; _compressionMode = FOURCC_V8U8; } _dds.Images[_level] = Decompress.Image(_imageBits, _w2, _h2, _compressionMode); } catch { // Unexpected end of file. Perhaps mipmaps weren't fully written to file. // We'll at least provide them with what we've extracted so far. _dds.MipMapCount = _level; if (_level == 0) { _dds.Images = null; throw new FileFormatException("Unable to read pixel data."); } else { Array.Resize<Bitmap>(ref _dds.Images, _level); } } } } return _dds; }