예제 #1
0
파일: DDSImage.cs 프로젝트: Xackery/EQZip
 public static bool Save(DDSImage Image, string Filename, CompressionMode Format)
 {
     try
     {
         return Save(Image.Images[0], Filename, Format);
     }
     catch
     {
         return false;
     }
 }
예제 #2
0
파일: DDSImage.cs 프로젝트: Xackery/EQZip
 public static bool Save(DDSImage Image, Stream Stream, CompressionMode Format)
 {
     try
     {
         return Save(Image.Images[0], Stream, Format);
     }
     catch
     {
         return false;
     }
 }
예제 #3
0
파일: DDSImage.cs 프로젝트: Xackery/EQZip
        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;
        }