Example #1
0
        public static void Save(
            Document input,
            Stream output,
            DdsFileFormat format,
            DdsErrorMetric errorMetric,
            BC7CompressionMode compressionMode,
            bool cubeMap,
            bool generateMipmaps,
            MipMapSampling sampling,
            Surface scratchSurface,
            ProgressEventHandler progressCallback)
        {
            using (RenderArgs args = new RenderArgs(scratchSurface))
            {
                input.Render(args, true);
            }

            DdsProgressCallback ddsProgress = null;

            if (progressCallback != null)
            {
                ddsProgress = (UIntPtr done, UIntPtr total) =>
                {
                    double progress = (double)done.ToUInt64() / (double)total.ToUInt64();
                    progressCallback(null, new ProgressEventArgs(progress * 100.0, true));
                };
            }

            SaveDdsFile(scratchSurface, format, errorMetric, compressionMode, cubeMap, generateMipmaps, sampling, output, ddsProgress);
        }
Example #2
0
 public static void PNG_To_DDS(string From_PNG_File, string To_DDS_File, DdsFileFormat Format)
 {
     //こっちのコードもメモリリークしていますが、GCで解放されるため放置
     System.IO.FileStream fileStream = new System.IO.FileStream(To_DDS_File, System.IO.FileMode.Create);
     DdsFile.Save(fileStream, Format, DdsErrorMetric.Perceptual, BC7CompressionMode.Slow, false, false, ResamplingAlgorithm.Bilinear, Surface.CopyFromBitmap(new Bitmap(From_PNG_File)), null);
     fileStream.Close();
 }
            internal DdsPixelFormat(DdsFileFormat format)
            {
                this.size = SizeOf;
                switch (format)
                {
                case DdsFileFormat.R8G8B8X8:
                    this.flags       = PixelFormatFlags.Rgb;
                    this.fourCC      = 0;
                    this.RGBBitCount = 32;
                    this.RBitMask    = 0x000000ff;
                    this.GBitMask    = 0x0000ff00;
                    this.BBitMask    = 0x00ff0000;
                    this.ABitMask    = 0x00000000;
                    break;

                case DdsFileFormat.B8G8R8:
                    this.flags       = PixelFormatFlags.Rgb;
                    this.fourCC      = 0;
                    this.RGBBitCount = 24;
                    this.RBitMask    = 0x00ff0000;
                    this.GBitMask    = 0x0000ff00;
                    this.BBitMask    = 0x000000ff;
                    this.ABitMask    = 0x00000000;
                    break;

                default:
                    throw new InvalidOperationException(GetUnsupportedFormatMessage(format));
                }
            }
Example #4
0
		public DdsSaveConfigToken( DdsFileFormat fileFormat, int compressorType, int errorMetric, bool weightColourByAlpha, bool generateMipMaps )
		{
			m_fileFormat			= fileFormat;
			m_compressorType		= compressorType;
			m_errorMetric			= errorMetric;
			m_weightColourByAlpha	= weightColourByAlpha;
			m_generateMipMaps		= generateMipMaps;
		}
 public DdsSaveConfigToken(DdsFileFormat fileFormat, int compressorType, int errorMetric, bool weightColourByAlpha, bool generateMipMaps)
 {
     m_fileFormat          = fileFormat;
     m_compressorType      = compressorType;
     m_errorMetric         = errorMetric;
     m_weightColourByAlpha = weightColourByAlpha;
     m_generateMipMaps     = generateMipMaps;
 }
Example #6
0
        protected override void OnSaveT(Document input, Stream output, PropertyBasedSaveConfigToken token, Surface scratchSurface, ProgressEventHandler progressCallback)
        {
            DdsFileFormat      fileFormat      = (DdsFileFormat)token.GetProperty(PropertyNames.FileFormat).Value;
            BC7CompressionMode compressionMode = (BC7CompressionMode)token.GetProperty(PropertyNames.BC7CompressionMode).Value;
            DdsErrorMetric     errorMetric     = (DdsErrorMetric)token.GetProperty(PropertyNames.ErrorMetric).Value;
            bool           generateMipmaps     = token.GetProperty <BooleanProperty>(PropertyNames.GenerateMipMaps).Value;
            MipMapSampling mipSampling         = (MipMapSampling)token.GetProperty(PropertyNames.MipMapResamplingAlgorithm).Value;

            DdsFile.Save(input, output, fileFormat, errorMetric, compressionMode, generateMipmaps, mipSampling, scratchSurface, progressCallback);
        }
        protected override bool IsReflexive(PropertyBasedSaveConfigToken token)
        {
            if (token.GetProperty <BooleanProperty>(PropertyNames.CubeMap).Value)
            {
                return(false);
            }

            DdsFileFormat format = (DdsFileFormat)token.GetProperty(PropertyNames.FileFormat).Value;

            return(format == DdsFileFormat.B8G8R8A8 || format == DdsFileFormat.R8G8B8A8);
        }
Example #8
0
        private static void SaveDdsFile(
            Surface surface,
            DdsFileFormat format,
            DdsErrorMetric errorMetric,
            BC7CompressionMode compressionMode,
            bool cubeMap,
            bool generateMipmaps,
            MipMapSampling mipMapSampling,
            Stream output,
            DdsProgressCallback progressCallback)
        {
            DDSSaveInfo info = new DDSSaveInfo
            {
                scan0           = surface.Scan0.Pointer,
                width           = surface.Width,
                height          = surface.Height,
                stride          = surface.Stride,
                format          = format,
                errorMetric     = errorMetric,
                compressionMode = compressionMode,
                cubeMap         = cubeMap && IsCrossedCubeMapSize(surface),
                generateMipmaps = generateMipmaps,
                mipmapSampling  = mipMapSampling
            };

            StreamIOCallbacks streamIO  = new StreamIOCallbacks(output);
            IOCallbacks       callbacks = new IOCallbacks
            {
                Read    = streamIO.Read,
                Write   = streamIO.Write,
                Seek    = streamIO.Seek,
                GetSize = streamIO.GetSize
            };

            int hr;

            if (IntPtr.Size == 8)
            {
                hr = DdsIO_x64.Save(ref info, callbacks, progressCallback);
            }
            else
            {
                hr = DdsIO_x86.Save(ref info, callbacks, progressCallback);
            }

            GC.KeepAlive(streamIO);
            GC.KeepAlive(callbacks);
            GC.KeepAlive(progressCallback);

            if (FAILED(hr))
            {
                Marshal.ThrowExceptionForHR(hr);
            }
        }
Example #9
0
        protected override void OnSaveT(Document input, Stream output, PropertyBasedSaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback)
        {
            scratchSurface.Clear(ColorBgra.Zero);
            using (RenderArgs args = new RenderArgs(scratchSurface))
            {
                input.Render(args, true);
            }
            DdsFileFormat     fileFormat     = (DdsFileFormat)token.GetProperty <StaticListChoiceProperty>(PropertyNames.FileFormat).Value;
            DdsCompressorType compressorType = (DdsCompressorType)token.GetProperty <StaticListChoiceProperty>(PropertyNames.CompressorType).Value;
            DdsErrorMetric    errorMetric    = (DdsErrorMetric)token.GetProperty <StaticListChoiceProperty>(PropertyNames.ErrorMetric).Value;
            bool weightColorByAlpha          = token.GetProperty <BooleanProperty>(PropertyNames.WeightColorByAlpha).Value;
            bool generateMipMaps             = token.GetProperty <BooleanProperty>(PropertyNames.GenerateMipMaps).Value;
            ResamplingAlgorithm mipMapResamplingAlgorithm = (ResamplingAlgorithm)token.GetProperty <StaticListChoiceProperty>(PropertyNames.MipMapResamplingAlgorithm).Value;

            new DdsFile().Save(output, scratchSurface, fileFormat, compressorType, errorMetric, generateMipMaps, mipMapResamplingAlgorithm, weightColorByAlpha, callback);
        }
Example #10
0
        private int GetSquishFlags(DdsFileFormat fileFormat, DdsCompressorType compressorType, DdsErrorMetric errorMetric, bool weightColorByAlpha)
        {
            int num = 0;

            if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT1)
            {
                num |= 1;
            }
            else if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT3)
            {
                num |= 2;
            }
            else if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT5)
            {
                num |= 4;
            }
            if (num != 0)
            {
                if (compressorType == DdsCompressorType.ClusterFit)
                {
                    num |= 8;
                }
                else if (compressorType == DdsCompressorType.RangeFit)
                {
                    num |= 0x10;
                }
                else
                {
                    num |= 0x100;
                }
                if (errorMetric == DdsErrorMetric.Perceptual)
                {
                    num |= 0x20;
                }
                else
                {
                    num |= 0x40;
                }
                if ((compressorType == DdsCompressorType.ClusterFit) & weightColorByAlpha)
                {
                    num |= 0x80;
                }
            }
            return(num);
        }
            internal DdsHeader(int width, int height, int arraySize, int mipCount, DdsFileFormat format)
            {
                this.size   = SizeOf;
                this.flags  = HeaderFlags.Texture;
                this.height = (uint)height;
                this.width  = (uint)width;
                switch (format)
                {
                case DdsFileFormat.R8G8B8X8:
                    this.flags            |= HeaderFlags.Pitch;
                    this.pitchOrLinearSize = (((uint)width * 32) + 7) / 8;
                    break;

                case DdsFileFormat.B8G8R8:
                    this.flags            |= HeaderFlags.Pitch;
                    this.pitchOrLinearSize = (((uint)width * 24) + 7) / 8;
                    break;

                default:
                    throw new InvalidOperationException(GetUnsupportedFormatMessage(format));
                }
                this.depth = 1;
                if (mipCount > 1)
                {
                    this.flags      |= HeaderFlags.Mipmap;
                    this.mipMapCount = (uint)mipCount;
                    this.caps       |= SurfaceFlags.Mipmap;
                }
                else
                {
                    this.mipMapCount = 1;
                }
                this.reserved1 = new uint[11];
                this.ddspf     = new DdsPixelFormat(format);
                this.caps     |= SurfaceFlags.Texture;
                if (arraySize == 6)
                {
                    this.caps  |= SurfaceFlags.Cubemap;
                    this.caps2 |= CubemapFaces.All;
                }
                this.caps3     = 0;
                this.caps4     = 0;
                this.reserved2 = 0;
            }
        private const uint DdsMagic = 0x20534444; // "DDS "

        internal DX9DdsWriter(int width, int height, int arraySize, int mipLevels, DdsFileFormat format)
        {
            this.width     = width;
            this.height    = height;
            this.arraySize = arraySize;
            this.mipLevels = mipLevels;
            this.format    = format;

            switch (format)
            {
            case DdsFileFormat.R8G8B8X8:
                this.pixelBuffer = new byte[4];
                break;

            case DdsFileFormat.B8G8R8:
                this.pixelBuffer = new byte[3];
                break;

            default:
                throw new InvalidOperationException(GetUnsupportedFormatMessage(format));
            }
        }
Example #13
0
        private static unsafe void SaveDdsFile(
            Surface surface,
            DdsFileFormat format,
            DdsErrorMetric errorMetric,
            BC7CompressionMode compressionMode,
            bool generateMipmaps,
            MipMapSampling mipMapSampling,
            DdsWriteImageCallback writeImageCallback,
            DdsProgressCallback progressCallback)
        {
            DDSSaveInfo info = new DDSSaveInfo
            {
                width           = surface.Width,
                height          = surface.Height,
                stride          = surface.Stride,
                format          = format,
                errorMetric     = errorMetric,
                compressionMode = compressionMode,
                generateMipmaps = generateMipmaps,
                mipmapSampling  = mipMapSampling,
                scan0           = surface.Scan0.Pointer
            };

            int hr;

            if (IntPtr.Size == 8)
            {
                hr = DdsIO_x64.Save(ref info, writeImageCallback, progressCallback);
            }
            else
            {
                hr = DdsIO_x86.Save(ref info, writeImageCallback, progressCallback);
            }

            if (FAILED(hr))
            {
                Marshal.ThrowExceptionForHR(hr);
            }
        }
Example #14
0
        public void Initialize(DdsFileFormat fileFormat)
        {
            switch (fileFormat)
            {
            case DdsFileFormat.DDS_FORMAT_DXT1:
            case DdsFileFormat.DDS_FORMAT_DXT3:
            case DdsFileFormat.DDS_FORMAT_DXT5:
                this.Flags       = (UInt32)PixelFormatFlags.DDS_FOURCC;
                this.RgbBitCount = 0x00000000;
                this.BitMaskA    = 0x00000000;
                this.BitMaskR    = 0x00000000;
                this.BitMaskG    = 0x00000000;
                this.BitMaskB    = 0x00000000;
                if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT1)
                {
                    this.FourCC = 0x31545844; //"DXT1"
                }
                if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT3)
                {
                    this.FourCC = 0x33545844; //"DXT3"
                }
                if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT5)
                {
                    this.FourCC = 0x35545844; //"DXT5"
                }
                break;

            case DdsFileFormat.DDS_FORMAT_A8R8G8B8:
                this.Flags       = (UInt32)PixelFormatFlags.DDS_RGBA;
                this.RgbBitCount = 0x000000020;
                this.FourCC      = 0;
                this.BitMaskA    = 0xff000000;
                this.BitMaskR    = 0x00ff0000;
                this.BitMaskG    = 0x0000ff00;
                this.BitMaskB    = 0x000000ff;
                break;

            case DdsFileFormat.DDS_FORMAT_X8R8G8B8:
                this.Flags       = (UInt32)PixelFormatFlags.DDS_RGB;
                this.RgbBitCount = 0x00000020;
                this.FourCC      = 0x00000000;
                this.BitMaskA    = 0x00000000;
                this.BitMaskR    = 0x00ff0000;
                this.BitMaskG    = 0x0000ff00;
                this.BitMaskB    = 0x000000ff;
                break;

            case DdsFileFormat.DDS_FORMAT_A8B8G8R8:
                this.Flags       = (UInt32)PixelFormatFlags.DDS_RGBA;
                this.RgbBitCount = 0x00000020;
                this.FourCC      = 0x00000000;
                this.BitMaskA    = 0xff000000;
                this.BitMaskR    = 0x000000ff;
                this.BitMaskG    = 0x0000ff00;
                this.BitMaskB    = 0x00ff0000;
                break;

            case DdsFileFormat.DDS_FORMAT_X8B8G8R8:
                this.Flags       = (UInt32)PixelFormatFlags.DDS_RGB;
                this.RgbBitCount = 0x00000020;
                this.FourCC      = 0x00000000;
                this.BitMaskA    = 0x00000000;
                this.BitMaskR    = 0x000000ff;
                this.BitMaskG    = 0x0000ff00;
                this.BitMaskB    = 0x00ff0000;
                break;

            case DdsFileFormat.DDS_FORMAT_A1R5G5B5:
                this.Flags       = (UInt32)PixelFormatFlags.DDS_RGBA;
                this.RgbBitCount = 0x00000010;
                this.FourCC      = 0x00000000;
                this.BitMaskA    = 0x00008000;
                this.BitMaskR    = 0x00007c00;
                this.BitMaskG    = 0x000003e0;
                this.BitMaskB    = 0x0000001f;
                break;

            case DdsFileFormat.DDS_FORMAT_A4R4G4B4:
                this.Flags       = (UInt32)PixelFormatFlags.DDS_RGBA;
                this.RgbBitCount = 16;
                this.FourCC      = 0;
                this.BitMaskA    = 0x0000f000;
                this.BitMaskR    = 0x00000f00;
                this.BitMaskG    = 0x000000f0;
                this.BitMaskB    = 0x0000000f;
                break;

            case DdsFileFormat.DDS_FORMAT_R8G8B8:
                this.Flags       = (UInt32)PixelFormatFlags.DDS_RGB;
                this.RgbBitCount = 0x00000018;
                this.FourCC      = 0x00000000;
                this.BitMaskA    = 0x00000000;
                this.BitMaskR    = 0x00ff0000;
                this.BitMaskG    = 0x0000ff00;
                this.BitMaskB    = 0x000000ff;
                break;

            case DdsFileFormat.DDS_FORMAT_R5G6B5:
                this.Flags       = (UInt32)PixelFormatFlags.DDS_RGB;
                this.RgbBitCount = 0x00000010;
                this.FourCC      = 0x00000000;
                this.BitMaskA    = 0x00000000;
                this.BitMaskR    = 0x0000f800;
                this.BitMaskG    = 0x000007e0;
                this.BitMaskB    = 0x0000001f;
                break;

            default:
                break;
            }
        }
Example #15
0
		public void Initialise( DdsFileFormat fileFormat )
		{
			m_size = Size();
			switch( fileFormat )
			{
				case	DdsFileFormat.DXT1:
				case	DdsFileFormat.DXT3:
				case	DdsFileFormat.DXT5:
				{
					// DXT1/DXT3/DXT5
					m_flags			= ( int )PixelFormatFlags.FourCC;
					m_rgbBitCount	=	0;
					m_rBitMask		=	0;
					m_gBitMask		=	0;
					m_bBitMask		=	0;
					m_aBitMask		=	0;
					if ( fileFormat == DdsFileFormat.DXT1 ) m_fourCC = 0x31545844;	//"DXT1"
					if ( fileFormat == DdsFileFormat.DXT3 ) m_fourCC = 0x33545844;	//"DXT1"
					if ( fileFormat == DdsFileFormat.DXT5 ) m_fourCC = 0x35545844;	//"DXT1"
					break;
				}
	
				case	DdsFileFormat.A8R8G8B8:
				{	
					m_flags			= ( int )PixelFormatFlags.RGBA;
					m_rgbBitCount	= 32;
					m_fourCC		= 0;
					m_rBitMask		= 0x00ff0000;
					m_gBitMask		= 0x0000ff00;
					m_bBitMask		= 0x000000ff;
					m_aBitMask		= 0xff000000;
					break;
				}

				case	DdsFileFormat.X8R8G8B8:
				{	
					m_flags			= ( int )PixelFormatFlags.RGB;
					m_rgbBitCount	= 32;
					m_fourCC		= 0;
					m_rBitMask		= 0x00ff0000;
					m_gBitMask		= 0x0000ff00;
					m_bBitMask		= 0x000000ff;
					m_aBitMask		= 0x00000000;
					break;
				}

				case	DdsFileFormat.A8B8G8R8:
				{	
					m_flags			= ( int )PixelFormatFlags.RGBA;
					m_rgbBitCount	= 32;
					m_fourCC		= 0;
					m_rBitMask		= 0x000000ff;
					m_gBitMask		= 0x0000ff00;
					m_bBitMask		= 0x00ff0000;
					m_aBitMask		= 0xff000000;
					break;
				}

				case	DdsFileFormat.X8B8G8R8:
				{	
					m_flags			= ( int )PixelFormatFlags.RGB;
					m_rgbBitCount	= 32;
					m_fourCC		= 0;
					m_rBitMask		= 0x000000ff;
					m_gBitMask		= 0x0000ff00;
					m_bBitMask		= 0x00ff0000;
					m_aBitMask		= 0x00000000;
					break;
				}

				case	DdsFileFormat.A1R5G5B5:
				{	
					m_flags			= ( int )PixelFormatFlags.RGBA;
					m_rgbBitCount	= 16;
					m_fourCC		= 0;
					m_rBitMask		= 0x00007c00;
					m_gBitMask		= 0x000003e0;
					m_bBitMask		= 0x0000001f;
					m_aBitMask		= 0x00008000;
					break;
				}

				case	DdsFileFormat.A4R4G4B4:
				{	
					m_flags			= ( int )PixelFormatFlags.RGBA;
					m_rgbBitCount	= 16;
					m_fourCC		= 0;
					m_rBitMask		= 0x00000f00;
					m_gBitMask		= 0x000000f0;
					m_bBitMask		= 0x0000000f;
					m_aBitMask		= 0x0000f000;
					break;
				}

				case	DdsFileFormat.R8G8B8:
				{	
					m_flags			= ( int )PixelFormatFlags.RGB;
					m_fourCC		= 0;
					m_rgbBitCount	= 24;
					m_rBitMask		= 0x00ff0000;
					m_gBitMask		= 0x0000ff00;
					m_bBitMask		= 0x000000ff;
					m_aBitMask		= 0x00000000;
					break;
				}

				case	DdsFileFormat.R5G6B5:
				{	
					m_flags			= ( int )PixelFormatFlags.RGB;
					m_fourCC		= 0;
					m_rgbBitCount	= 16;
					m_rBitMask		= 0x0000f800;
					m_gBitMask		= 0x000007e0;
					m_bBitMask		= 0x0000001f;
					m_aBitMask		= 0x00000000;
					break;
				}
		
				default:
					break;
			}
		}
Example #16
0
        protected override bool IsReflexive(PropertyBasedSaveConfigToken token)
        {
            DdsFileFormat format = (DdsFileFormat)token.GetProperty(PropertyNames.FileFormat).Value;

            return(format == DdsFileFormat.B8G8R8A8 || format == DdsFileFormat.R8G8B8A8);
        }
Example #17
0
        public void Initialise(DdsFileFormat fileFormat)
        {
            m_size = Size();
            switch (fileFormat)
            {
            case    DdsFileFormat.DDS_FORMAT_DXT1:
            case    DdsFileFormat.DDS_FORMAT_DXT3:
            case    DdsFileFormat.DDS_FORMAT_DXT5:
            {
                // DXT1/DXT3/DXT5
                m_flags       = ( int )PixelFormatFlags.DDS_FOURCC;
                m_rgbBitCount = 0;
                m_rBitMask    = 0;
                m_gBitMask    = 0;
                m_bBitMask    = 0;
                m_aBitMask    = 0;
                if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT1)
                {
                    m_fourCC = 0x31545844;                                                                              //"DXT1"
                }
                if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT3)
                {
                    m_fourCC = 0x33545844;                                                                              //"DXT1"
                }
                if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT5)
                {
                    m_fourCC = 0x35545844;                                                                              //"DXT1"
                }
                break;
            }

            case    DdsFileFormat.DDS_FORMAT_A8R8G8B8:
            {
                m_flags       = ( int )PixelFormatFlags.DDS_RGBA;
                m_rgbBitCount = 32;
                m_fourCC      = 0;
                m_rBitMask    = 0x00ff0000;
                m_gBitMask    = 0x0000ff00;
                m_bBitMask    = 0x000000ff;
                m_aBitMask    = 0xff000000;
                break;
            }

            case    DdsFileFormat.DDS_FORMAT_X8R8G8B8:
            {
                m_flags       = ( int )PixelFormatFlags.DDS_RGB;
                m_rgbBitCount = 32;
                m_fourCC      = 0;
                m_rBitMask    = 0x00ff0000;
                m_gBitMask    = 0x0000ff00;
                m_bBitMask    = 0x000000ff;
                m_aBitMask    = 0x00000000;
                break;
            }

            case    DdsFileFormat.DDS_FORMAT_A8B8G8R8:
            {
                m_flags       = ( int )PixelFormatFlags.DDS_RGBA;
                m_rgbBitCount = 32;
                m_fourCC      = 0;
                m_rBitMask    = 0x000000ff;
                m_gBitMask    = 0x0000ff00;
                m_bBitMask    = 0x00ff0000;
                m_aBitMask    = 0xff000000;
                break;
            }

            case    DdsFileFormat.DDS_FORMAT_X8B8G8R8:
            {
                m_flags       = ( int )PixelFormatFlags.DDS_RGB;
                m_rgbBitCount = 32;
                m_fourCC      = 0;
                m_rBitMask    = 0x000000ff;
                m_gBitMask    = 0x0000ff00;
                m_bBitMask    = 0x00ff0000;
                m_aBitMask    = 0x00000000;
                break;
            }

            case    DdsFileFormat.DDS_FORMAT_A1R5G5B5:
            {
                m_flags       = ( int )PixelFormatFlags.DDS_RGBA;
                m_rgbBitCount = 16;
                m_fourCC      = 0;
                m_rBitMask    = 0x00007c00;
                m_gBitMask    = 0x000003e0;
                m_bBitMask    = 0x0000001f;
                m_aBitMask    = 0x00008000;
                break;
            }

            case    DdsFileFormat.DDS_FORMAT_A4R4G4B4:
            {
                m_flags       = ( int )PixelFormatFlags.DDS_RGBA;
                m_rgbBitCount = 16;
                m_fourCC      = 0;
                m_rBitMask    = 0x00000f00;
                m_gBitMask    = 0x000000f0;
                m_bBitMask    = 0x0000000f;
                m_aBitMask    = 0x0000f000;
                break;
            }

            case    DdsFileFormat.DDS_FORMAT_R8G8B8:
            {
                m_flags       = ( int )PixelFormatFlags.DDS_RGB;
                m_fourCC      = 0;
                m_rgbBitCount = 24;
                m_rBitMask    = 0x00ff0000;
                m_gBitMask    = 0x0000ff00;
                m_bBitMask    = 0x000000ff;
                m_aBitMask    = 0x00000000;
                break;
            }

            case    DdsFileFormat.DDS_FORMAT_R5G6B5:
            {
                m_flags       = ( int )PixelFormatFlags.DDS_RGB;
                m_fourCC      = 0;
                m_rgbBitCount = 16;
                m_rBitMask    = 0x0000f800;
                m_gBitMask    = 0x000007e0;
                m_bBitMask    = 0x0000001f;
                m_aBitMask    = 0x00000000;
                break;
            }

            default:
                break;
            }
        }
Example #18
0
        public void    Load(System.IO.Stream input)
        {
            // Read the DDS tag. If it's not right, then bail..
            uint ddsTag = ( uint )Utility.ReadUInt32(input);

            if (ddsTag != 0x20534444)
            {
                throw new FormatException("File does not appear to be a DDS image");
            }

            // Read everything in.. for now assume it worked like a charm..
            m_header.Read(input);

            if ((m_header.m_pixelFormat.m_flags & ( int )DdsPixelFormat.PixelFormatFlags.DDS_FOURCC) != 0)
            {
                int squishFlags = 0;

                switch (m_header.m_pixelFormat.m_fourCC)
                {
                case    0x31545844:
                    squishFlags = ( int )DdsSquish.SquishFlags.kDxt1;
                    break;

                case    0x33545844:
                    squishFlags = ( int )DdsSquish.SquishFlags.kDxt3;
                    break;

                case    0x35545844:
                    squishFlags = ( int )DdsSquish.SquishFlags.kDxt5;
                    break;

                default:
                    throw new FormatException("File is not a supported DDS format");
                }

                // Compute size of compressed block area
                int blockCount = ((GetWidth() + 3) / 4) * ((GetHeight() + 3) / 4);
                int blockSize  = ((squishFlags & ( int )DdsSquish.SquishFlags.kDxt1) != 0) ? 8 : 16;

                // Allocate room for compressed blocks, and read data into it.
                byte[] compressedBlocks = new byte[blockCount * blockSize];
                input.Read(compressedBlocks, 0, compressedBlocks.GetLength(0));

                // Now decompress..
                m_pixelData = DdsSquish.DecompressImage(compressedBlocks, GetWidth(), GetHeight(), squishFlags);
            }
            else
            {
                // We can only deal with the non-DXT formats we know about..  this is a bit of a mess..
                // Sorry..
                DdsFileFormat fileFormat = DdsFileFormat.DDS_FORMAT_INVALID;

                if ((m_header.m_pixelFormat.m_flags == ( int )DdsPixelFormat.PixelFormatFlags.DDS_RGBA) &&
                    (m_header.m_pixelFormat.m_rgbBitCount == 32) &&
                    (m_header.m_pixelFormat.m_rBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                    (m_header.m_pixelFormat.m_bBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_aBitMask == 0xff000000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_A8R8G8B8;
                }
                else
                if ((m_header.m_pixelFormat.m_flags == ( int )DdsPixelFormat.PixelFormatFlags.DDS_RGB) &&
                    (m_header.m_pixelFormat.m_rgbBitCount == 32) &&
                    (m_header.m_pixelFormat.m_rBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                    (m_header.m_pixelFormat.m_bBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_aBitMask == 0x00000000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_X8R8G8B8;
                }
                else
                if ((m_header.m_pixelFormat.m_flags == ( int )DdsPixelFormat.PixelFormatFlags.DDS_RGBA) &&
                    (m_header.m_pixelFormat.m_rgbBitCount == 32) &&
                    (m_header.m_pixelFormat.m_rBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                    (m_header.m_pixelFormat.m_bBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_aBitMask == 0xff000000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_A8B8G8R8;
                }
                else
                if ((m_header.m_pixelFormat.m_flags == ( int )DdsPixelFormat.PixelFormatFlags.DDS_RGB) &&
                    (m_header.m_pixelFormat.m_rgbBitCount == 32) &&
                    (m_header.m_pixelFormat.m_rBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                    (m_header.m_pixelFormat.m_bBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_aBitMask == 0x00000000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_X8B8G8R8;
                }
                else
                if ((m_header.m_pixelFormat.m_flags == ( int )DdsPixelFormat.PixelFormatFlags.DDS_RGBA) &&
                    (m_header.m_pixelFormat.m_rgbBitCount == 16) &&
                    (m_header.m_pixelFormat.m_rBitMask == 0x00007c00) && (m_header.m_pixelFormat.m_gBitMask == 0x000003e0) &&
                    (m_header.m_pixelFormat.m_bBitMask == 0x0000001f) && (m_header.m_pixelFormat.m_aBitMask == 0x00008000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_A1R5G5B5;
                }
                else
                if ((m_header.m_pixelFormat.m_flags == ( int )DdsPixelFormat.PixelFormatFlags.DDS_RGBA) &&
                    (m_header.m_pixelFormat.m_rgbBitCount == 16) &&
                    (m_header.m_pixelFormat.m_rBitMask == 0x00000f00) && (m_header.m_pixelFormat.m_gBitMask == 0x000000f0) &&
                    (m_header.m_pixelFormat.m_bBitMask == 0x0000000f) && (m_header.m_pixelFormat.m_aBitMask == 0x0000f000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_A4R4G4B4;
                }
                else
                if ((m_header.m_pixelFormat.m_flags == ( int )DdsPixelFormat.PixelFormatFlags.DDS_RGB) &&
                    (m_header.m_pixelFormat.m_rgbBitCount == 24) &&
                    (m_header.m_pixelFormat.m_rBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                    (m_header.m_pixelFormat.m_bBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_aBitMask == 0x00000000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_R8G8B8;
                }
                else
                if ((m_header.m_pixelFormat.m_flags == ( int )DdsPixelFormat.PixelFormatFlags.DDS_RGB) &&
                    (m_header.m_pixelFormat.m_rgbBitCount == 16) &&
                    (m_header.m_pixelFormat.m_rBitMask == 0x0000f800) && (m_header.m_pixelFormat.m_gBitMask == 0x000007e0) &&
                    (m_header.m_pixelFormat.m_bBitMask == 0x0000001f) && (m_header.m_pixelFormat.m_aBitMask == 0x00000000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_R5G6B5;
                }

                // If fileFormat is still invalid, then it's an unsupported format.
                if (fileFormat == DdsFileFormat.DDS_FORMAT_INVALID)
                {
                    throw new FormatException("File is not a supported DDS format");
                }

                // Size of a source pixel, in bytes
                int srcPixelSize = (( int )m_header.m_pixelFormat.m_rgbBitCount / 8);

                // We need the pitch for a row, so we can allocate enough memory for the load.
                int rowPitch = 0;

                if ((m_header.m_headerFlags & ( int )DdsHeader.HeaderFlags.DDS_HEADER_FLAGS_PITCH) != 0)
                {
                    // Pitch specified.. so we can use directly
                    rowPitch = ( int )m_header.m_pitchOrLinearSize;
                }
                else
                if ((m_header.m_headerFlags & ( int )DdsHeader.HeaderFlags.DDS_HEADER_FLAGS_LINEARSIZE) != 0)
                {
                    // Linear size specified.. compute row pitch. Of course, this should never happen
                    // as linear size is *supposed* to be for compressed textures. But Microsoft don't
                    // always play by the rules when it comes to DDS output.
                    rowPitch = ( int )m_header.m_pitchOrLinearSize / ( int )m_header.m_height;
                }
                else
                {
                    // Another case of Microsoft not obeying their standard is the 'Convert to..' shell extension
                    // that ships in the DirectX SDK. Seems to always leave flags empty..so no indication of pitch
                    // or linear size. And - to cap it all off - they leave pitchOrLinearSize as *zero*. Zero??? If
                    // we get this bizarre set of inputs, we just go 'screw it' and compute row pitch ourselves,
                    // making sure we DWORD align it (if that code path is enabled).
                    rowPitch = (( int )m_header.m_width * srcPixelSize);

#if     APPLY_PITCH_ALIGNMENT
                    rowPitch = ((( int )rowPitch + 3) & (~3));
#endif  // APPLY_PITCH_ALIGNMENT
                }

//				System.Diagnostics.Debug.WriteLine( "Image width : " + m_header.m_width + ", rowPitch = " + rowPitch );

                // Ok.. now, we need to allocate room for the bytes to read in from.. it's rowPitch bytes * height
                byte[] readPixelData = new byte[rowPitch * m_header.m_height];
                input.Read(readPixelData, 0, readPixelData.GetLength(0));

                // We now need space for the real pixel data.. that's width * height * 4..
                m_pixelData = new byte[m_header.m_width * m_header.m_height * 4];

                // And now we have the arduous task of filling that up with stuff..
                for (int destY = 0; destY < ( int )m_header.m_height; destY++)
                {
                    for (int destX = 0; destX < ( int )m_header.m_width; destX++)
                    {
                        // Compute source pixel offset
                        int srcPixelOffset = (destY * rowPitch) + (destX * srcPixelSize);

                        // Read our pixel
                        uint pixelColour = 0;
                        uint pixelRed    = 0;
                        uint pixelGreen  = 0;
                        uint pixelBlue   = 0;
                        uint pixelAlpha  = 0;

                        // Build our pixel colour as a DWORD
                        for (int loop = 0; loop < srcPixelSize; loop++)
                        {
                            pixelColour |= ( uint )(readPixelData[srcPixelOffset + loop] << (8 * loop));
                        }

                        if (fileFormat == DdsFileFormat.DDS_FORMAT_A8R8G8B8)
                        {
                            pixelAlpha = (pixelColour >> 24) & 0xff;
                            pixelRed   = (pixelColour >> 16) & 0xff;
                            pixelGreen = (pixelColour >> 8) & 0xff;
                            pixelBlue  = (pixelColour >> 0) & 0xff;
                        }
                        else
                        if (fileFormat == DdsFileFormat.DDS_FORMAT_X8R8G8B8)
                        {
                            pixelAlpha = 0xff;
                            pixelRed   = (pixelColour >> 16) & 0xff;
                            pixelGreen = (pixelColour >> 8) & 0xff;
                            pixelBlue  = (pixelColour >> 0) & 0xff;
                        }
                        else
                        if (fileFormat == DdsFileFormat.DDS_FORMAT_A8B8G8R8)
                        {
                            pixelAlpha = (pixelColour >> 24) & 0xff;
                            pixelRed   = (pixelColour >> 0) & 0xff;
                            pixelGreen = (pixelColour >> 8) & 0xff;
                            pixelBlue  = (pixelColour >> 16) & 0xff;
                        }
                        else
                        if (fileFormat == DdsFileFormat.DDS_FORMAT_X8B8G8R8)
                        {
                            pixelAlpha = 0xff;
                            pixelRed   = (pixelColour >> 0) & 0xff;
                            pixelGreen = (pixelColour >> 8) & 0xff;
                            pixelBlue  = (pixelColour >> 16) & 0xff;
                        }
                        else
                        if (fileFormat == DdsFileFormat.DDS_FORMAT_A1R5G5B5)
                        {
                            pixelAlpha = (pixelColour >> 15) * 0xff;
                            pixelRed   = (pixelColour >> 10) & 0x1f;
                            pixelGreen = (pixelColour >> 5) & 0x1f;
                            pixelBlue  = (pixelColour >> 0) & 0x1f;

                            pixelRed   = (pixelRed << 3) | (pixelRed >> 2);
                            pixelGreen = (pixelGreen << 3) | (pixelGreen >> 2);
                            pixelBlue  = (pixelBlue << 3) | (pixelBlue >> 2);
                        }
                        else
                        if (fileFormat == DdsFileFormat.DDS_FORMAT_A4R4G4B4)
                        {
                            pixelAlpha = (pixelColour >> 12) & 0xff;
                            pixelRed   = (pixelColour >> 8) & 0x0f;
                            pixelGreen = (pixelColour >> 4) & 0x0f;
                            pixelBlue  = (pixelColour >> 0) & 0x0f;

                            pixelAlpha = (pixelAlpha << 4) | (pixelAlpha >> 0);
                            pixelRed   = (pixelRed << 4) | (pixelRed >> 0);
                            pixelGreen = (pixelGreen << 4) | (pixelGreen >> 0);
                            pixelBlue  = (pixelBlue << 4) | (pixelBlue >> 0);
                        }
                        else
                        if (fileFormat == DdsFileFormat.DDS_FORMAT_R8G8B8)
                        {
                            pixelAlpha = 0xff;
                            pixelRed   = (pixelColour >> 16) & 0xff;
                            pixelGreen = (pixelColour >> 8) & 0xff;
                            pixelBlue  = (pixelColour >> 0) & 0xff;
                        }
                        else
                        if (fileFormat == DdsFileFormat.DDS_FORMAT_R5G6B5)
                        {
                            pixelAlpha = 0xff;
                            pixelRed   = (pixelColour >> 11) & 0x1f;
                            pixelGreen = (pixelColour >> 5) & 0x3f;
                            pixelBlue  = (pixelColour >> 0) & 0x1f;

                            pixelRed   = (pixelRed << 3) | (pixelRed >> 2);
                            pixelGreen = (pixelGreen << 2) | (pixelGreen >> 4);
                            pixelBlue  = (pixelBlue << 3) | (pixelBlue >> 2);
                        }

                        // Write the colours away..
                        int destPixelOffset = (destY * ( int )m_header.m_width * 4) + (destX * 4);
                        m_pixelData[destPixelOffset + 0] = ( byte )pixelRed;
                        m_pixelData[destPixelOffset + 1] = ( byte )pixelGreen;
                        m_pixelData[destPixelOffset + 2] = ( byte )pixelBlue;
                        m_pixelData[destPixelOffset + 3] = ( byte )pixelAlpha;
                    }
                }
            }
        }
Example #19
0
        public static unsafe void Save(
            Document input,
            Stream output,
            DdsFileFormat format,
            DdsErrorMetric errorMetric,
            BC7CompressionMode compressionMode,
            bool generateMipmaps,
            MipMapSampling sampling,
            Surface scratchSurface,
            ProgressEventHandler progressCallback)
        {
            using (RenderArgs args = new RenderArgs(scratchSurface))
            {
                input.Render(args, true);
            }

            DdsWriteImageCallback ddsWriteImage = delegate(IntPtr image, UIntPtr imageSize)
            {
                ulong size = imageSize.ToUInt64();

                if (image != IntPtr.Zero && size > 0)
                {
                    const int MaxBufferSize = 65536;

                    ulong  streamBufferSize = Math.Min(MaxBufferSize, size);
                    byte[] streamBuffer     = new byte[streamBufferSize];

                    output.SetLength(checked ((long)size));

                    ulong offset    = 0;
                    ulong remaining = size;

                    fixed(byte *destPtr = streamBuffer)
                    {
                        byte *srcPtr = (byte *)image.ToPointer();

                        while (remaining > 0)
                        {
                            ulong copySize = Math.Min(MaxBufferSize, remaining);

                            Buffer.MemoryCopy(srcPtr + offset, destPtr, streamBufferSize, copySize);

                            output.Write(streamBuffer, 0, (int)copySize);

                            offset    += copySize;
                            remaining -= copySize;
                        }
                    }
                }
            };

            DdsProgressCallback ddsProgress = delegate(UIntPtr done, UIntPtr total)
            {
                double progress = (double)done.ToUInt64() / (double)total.ToUInt64();
                progressCallback(null, new ProgressEventArgs(progress * 100.0, true));
            };

            SaveDdsFile(scratchSurface, format, errorMetric, compressionMode, generateMipmaps, sampling, ddsWriteImage, ddsProgress);

            GC.KeepAlive(ddsWriteImage);
        }
Example #20
0
        public void Initialise(DdsFileFormat fileFormat)
        {
            this.m_size = this.Size();
            switch (fileFormat)
            {
            case DdsFileFormat.DDS_FORMAT_DXT1:
            case DdsFileFormat.DDS_FORMAT_DXT3:
            case DdsFileFormat.DDS_FORMAT_DXT5:
                this.m_flags       = 4;
                this.m_rgbBitCount = 0;
                this.m_rBitMask    = 0;
                this.m_gBitMask    = 0;
                this.m_bBitMask    = 0;
                this.m_aBitMask    = 0;
                if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT1)
                {
                    this.m_fourCC = 0x31545844;
                }
                if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT3)
                {
                    this.m_fourCC = 0x33545844;
                }
                if (fileFormat != DdsFileFormat.DDS_FORMAT_DXT5)
                {
                    break;
                }
                this.m_fourCC = 0x35545844;
                return;

            case DdsFileFormat.DDS_FORMAT_A8R8G8B8:
                this.m_flags       = 0x41;
                this.m_rgbBitCount = 0x20;
                this.m_fourCC      = 0;
                this.m_rBitMask    = 0xff0000;
                this.m_gBitMask    = 0xff00;
                this.m_bBitMask    = 0xff;
                this.m_aBitMask    = 0xff000000;
                return;

            case DdsFileFormat.DDS_FORMAT_X8R8G8B8:
                this.m_flags       = 0x40;
                this.m_rgbBitCount = 0x20;
                this.m_fourCC      = 0;
                this.m_rBitMask    = 0xff0000;
                this.m_gBitMask    = 0xff00;
                this.m_bBitMask    = 0xff;
                this.m_aBitMask    = 0;
                return;

            case DdsFileFormat.DDS_FORMAT_A8B8G8R8:
                this.m_flags       = 0x41;
                this.m_rgbBitCount = 0x20;
                this.m_fourCC      = 0;
                this.m_rBitMask    = 0xff;
                this.m_gBitMask    = 0xff00;
                this.m_bBitMask    = 0xff0000;
                this.m_aBitMask    = 0xff000000;
                return;

            case DdsFileFormat.DDS_FORMAT_X8B8G8R8:
                this.m_flags       = 0x40;
                this.m_rgbBitCount = 0x20;
                this.m_fourCC      = 0;
                this.m_rBitMask    = 0xff;
                this.m_gBitMask    = 0xff00;
                this.m_bBitMask    = 0xff0000;
                this.m_aBitMask    = 0;
                return;

            case DdsFileFormat.DDS_FORMAT_A1R5G5B5:
                this.m_flags       = 0x41;
                this.m_rgbBitCount = 0x10;
                this.m_fourCC      = 0;
                this.m_rBitMask    = 0x7c00;
                this.m_gBitMask    = 0x3e0;
                this.m_bBitMask    = 0x1f;
                this.m_aBitMask    = 0x8000;
                return;

            case DdsFileFormat.DDS_FORMAT_A4R4G4B4:
                this.m_flags       = 0x41;
                this.m_rgbBitCount = 0x10;
                this.m_fourCC      = 0;
                this.m_rBitMask    = 0xf00;
                this.m_gBitMask    = 240;
                this.m_bBitMask    = 15;
                this.m_aBitMask    = 0xf000;
                return;

            case DdsFileFormat.DDS_FORMAT_R8G8B8:
                this.m_flags       = 0x40;
                this.m_fourCC      = 0;
                this.m_rgbBitCount = 0x18;
                this.m_rBitMask    = 0xff0000;
                this.m_gBitMask    = 0xff00;
                this.m_bBitMask    = 0xff;
                this.m_aBitMask    = 0;
                return;

            case DdsFileFormat.DDS_FORMAT_R5G6B5:
                this.m_flags       = 0x40;
                this.m_fourCC      = 0;
                this.m_rgbBitCount = 0x10;
                this.m_rBitMask    = 0xf800;
                this.m_gBitMask    = 0x7e0;
                this.m_bBitMask    = 0x1f;
                this.m_aBitMask    = 0;
                break;

            default:
                return;
            }
        }
        public void Load( System.IO.Stream input )
        {
            if (input == null) return;
            if (input.Length == 0) return;

            ReadWriteStream(input, this._rawDDS);
            input.Seek(0, SeekOrigin.Begin);

            BinaryReader Utility = new BinaryReader(input);

            // Read the DDS tag. If it's not right, then bail..
            uint	ddsTag = Utility.ReadUInt32( );
            if ( ddsTag != 0x20534444 )
                throw new FormatException( "File does not appear to be a DDS image" );

            // Read everything in.. for now assume it worked like a charm..
            m_header.Read( input );

            if ((m_header.m_pixelFormat.m_flags & (int)DdsPixelFormat.PixelFormatFlags.DDS_FOURCC) != 0)
            {
                //int	squishFlags = 0;
                DdsFileFormat ddsFormat = new DdsFileFormat();

                switch (m_header.m_pixelFormat.m_fourCC)
                {
                    case 0x31545844:
                        //squishFlags = ( int )DdsSquish.SquishFlags.kDxt1;
                        ddsFormat = DdsFileFormat.DDS_FORMAT_DXT1;
                        m_header.fileFormat = "DXT1";
                        break;

                    case 0x33545844:
                        //squishFlags = ( int )DdsSquish.SquishFlags.kDxt3;
                        ddsFormat = DdsFileFormat.DDS_FORMAT_DXT3;
                        m_header.fileFormat = "DXT3";
                        break;

                    case 0x35545844:
                        //squishFlags = ( int )DdsSquish.SquishFlags.kDxt5;
                        ddsFormat = DdsFileFormat.DDS_FORMAT_DXT5;
                        m_header.fileFormat = "DXT5";
                        break;
                    case 0x31495441:
                        ddsFormat = DdsFileFormat.DDS_FORMAT_ATI1;
                        m_header.fileFormat = "ATI1";
                        break;
                    case 0x32495441:
                        ddsFormat = DdsFileFormat.DDS_FORMAT_ATI2;
                        m_header.fileFormat = "ATI2";
                        break;

                    default:
                        throw new FormatException("File is not a supported DDS format");
                }

                // Compute size of compressed block area
                //int blockCount = ( ( GetWidth() + 3 )/4 ) * ( ( GetHeight() + 3 )/4 );
                //int blockSize = 0;
                //((squishFlags & (int)DdsSquish.SquishFlags.kDxt1) != 0) ? 8 : 16;
                //if ((squishFlags & (int)DdsFileFormat.DDS_FORMAT_DXT1) != 0)
                //{
                //blockSize = 8;
                //}
                //else
                //{
                //blockSize = 16;
                //}

                // Allocate room for compressed blocks, and read data into it.
                //byte[] compressedBlocks = new byte[ blockCount * blockSize ];
                //input.Read( compressedBlocks, 0, compressedBlocks.GetLength( 0 ) );

                // Now decompress..
                //m_pixelData = DdsSquish.DecompressImage( input, GetWidth(), GetHeight(), squishFlags );
                this.m_pixelData = DecodeTextureData(input, ddsFormat, GetWidth(), GetHeight(), 0, 0, false);
            }
            else
            {
                // We can only deal with the non-DXT formats we know about..  this is a bit of a mess..
                // Sorry..
                DdsFileFormat fileFormat = DdsFileFormat.DDS_FORMAT_INVALID;

                if ((m_header.m_pixelFormat.m_flags == (int)DdsPixelFormat.PixelFormatFlags.DDS_RGB + (int)DdsPixelFormat.PixelFormatFlags.DDS_ALPHAPIXELS) &&
                        (m_header.m_pixelFormat.m_rgbBitCount == 32) &&
                        (m_header.m_pixelFormat.m_rBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                        (m_header.m_pixelFormat.m_bBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_aBitMask == 0xff000000))
                { fileFormat = DdsFileFormat.DDS_FORMAT_A8R8G8B8; m_header.fileFormat = "ARGB8"; }
                else
                    if ((m_header.m_pixelFormat.m_flags == (int)DdsPixelFormat.PixelFormatFlags.DDS_RGB) &&
                            (m_header.m_pixelFormat.m_rgbBitCount == 32) &&
                            (m_header.m_pixelFormat.m_rBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                            (m_header.m_pixelFormat.m_bBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_aBitMask == 0x00000000))
                    { fileFormat = DdsFileFormat.DDS_FORMAT_X8R8G8B8; m_header.fileFormat = "X8RGB8"; }
                    else
                        if ((m_header.m_pixelFormat.m_flags == (int)DdsPixelFormat.PixelFormatFlags.DDS_RGB + (int)DdsPixelFormat.PixelFormatFlags.DDS_ALPHAPIXELS) &&
                                (m_header.m_pixelFormat.m_rgbBitCount == 32) &&
                                (m_header.m_pixelFormat.m_rBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                                (m_header.m_pixelFormat.m_bBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_aBitMask == 0xff000000))
                        { fileFormat = DdsFileFormat.DDS_FORMAT_A8B8G8R8; m_header.fileFormat = "ABGR8"; }
                        else
                            if ((m_header.m_pixelFormat.m_flags == (int)DdsPixelFormat.PixelFormatFlags.DDS_RGB) &&
                                    (m_header.m_pixelFormat.m_rgbBitCount == 32) &&
                                    (m_header.m_pixelFormat.m_rBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                                    (m_header.m_pixelFormat.m_bBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_aBitMask == 0x00000000))
                            { fileFormat = DdsFileFormat.DDS_FORMAT_X8B8G8R8; m_header.fileFormat = "XBGR8"; }
                            else
                                if ((m_header.m_pixelFormat.m_flags == (int)DdsPixelFormat.PixelFormatFlags.DDS_RGB + (int)DdsPixelFormat.PixelFormatFlags.DDS_ALPHAPIXELS) &&
                                        (m_header.m_pixelFormat.m_rgbBitCount == 16) &&
                                        (m_header.m_pixelFormat.m_rBitMask == 0x00007c00) && (m_header.m_pixelFormat.m_gBitMask == 0x000003e0) &&
                                        (m_header.m_pixelFormat.m_bBitMask == 0x0000001f) && (m_header.m_pixelFormat.m_aBitMask == 0x00008000))
                                { fileFormat = DdsFileFormat.DDS_FORMAT_A1R5G5B5; m_header.fileFormat = "ARGB"; }
                                else
                                    if ((m_header.m_pixelFormat.m_flags == (int)DdsPixelFormat.PixelFormatFlags.DDS_RGB + (int)DdsPixelFormat.PixelFormatFlags.DDS_ALPHAPIXELS) &&
                                            (m_header.m_pixelFormat.m_rgbBitCount == 16) &&
                                            (m_header.m_pixelFormat.m_rBitMask == 0x00000f00) && (m_header.m_pixelFormat.m_gBitMask == 0x000000f0) &&
                                            (m_header.m_pixelFormat.m_bBitMask == 0x0000000f) && (m_header.m_pixelFormat.m_aBitMask == 0x0000f000))
                                    {
                                        fileFormat = DdsFileFormat.DDS_FORMAT_A4R4G4B4;
                                        m_header.fileFormat = "ARGB4";
                                    }
                                    else
                                        if ((m_header.m_pixelFormat.m_flags == (int)DdsPixelFormat.PixelFormatFlags.DDS_RGB) &&
                                                (m_header.m_pixelFormat.m_rgbBitCount == 24) &&
                                                (m_header.m_pixelFormat.m_rBitMask == 0x00ff0000) && (m_header.m_pixelFormat.m_gBitMask == 0x0000ff00) &&
                                                (m_header.m_pixelFormat.m_bBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_aBitMask == 0x00000000))
                                        { fileFormat = DdsFileFormat.DDS_FORMAT_R8G8B8; m_header.fileFormat = "RGB8"; }
                                        else
                                            if ((m_header.m_pixelFormat.m_flags == (int)DdsPixelFormat.PixelFormatFlags.DDS_RGB) &&
                                                    (m_header.m_pixelFormat.m_rgbBitCount == 16) &&
                                                    (m_header.m_pixelFormat.m_rBitMask == 0x0000f800) && (m_header.m_pixelFormat.m_gBitMask == 0x000007e0) &&
                                                    (m_header.m_pixelFormat.m_bBitMask == 0x0000001f) && (m_header.m_pixelFormat.m_aBitMask == 0x00000000))
                                            { fileFormat = DdsFileFormat.DDS_FORMAT_R5G6B5; m_header.fileFormat = "RGB5"; }
                                            else
                                                if ((m_header.m_pixelFormat.m_flags == (int)DdsPixelFormat.PixelFormatFlags.DDS_LUMINANCE + (int)DdsPixelFormat.PixelFormatFlags.DDS_ALPHAPIXELS) &&
                                                    (m_header.m_pixelFormat.m_rgbBitCount == 16) &&
                                                    (m_header.m_pixelFormat.m_rBitMask == 0x000000ff) && (m_header.m_pixelFormat.m_gBitMask == 0x00000000) &&
                                                    (m_header.m_pixelFormat.m_bBitMask == 0x00000000) && (m_header.m_pixelFormat.m_aBitMask == 0x0000ff00))
                                                { fileFormat = DdsFileFormat.DDS_FORMAT_A8L8; m_header.fileFormat = "A8L8"; }

                // If fileFormat is still invalid, then it's an unsupported format.
                if (fileFormat == DdsFileFormat.DDS_FORMAT_INVALID)
                {
                    System.Windows.Forms.MessageBox.Show("File is not a supported DDS format");
                    return;

                }

                // Size of a source pixel, in bytes
                int srcPixelSize = ((int)m_header.m_pixelFormat.m_rgbBitCount / 8);

                // We need the pitch for a row, so we can allocate enough memory for the load.
                int rowPitch = 0;

                if ((m_header.m_headerFlags & (int)DdsHeader.HeaderFlags.DDS_HEADER_FLAGS_PITCH) != 0)
                {
                    // Pitch specified.. so we can use directly
                    rowPitch = (int)m_header.m_pitchOrLinearSize;
                }
                else
                    if ((m_header.m_headerFlags & (int)DdsHeader.HeaderFlags.DDS_HEADER_FLAGS_LINEARSIZE) != 0)
                    {
                        // Linear size specified.. compute row pitch. Of course, this should never happen
                        // as linear size is *supposed* to be for compressed textures. But Microsoft don't
                        // always play by the rules when it comes to DDS output.
                        rowPitch = (int)m_header.m_pitchOrLinearSize / (int)m_header.m_height;
                    }
                    else
                    {
                        // Another case of Microsoft not obeying their standard is the 'Convert to..' shell extension
                        // that ships in the DirectX SDK. Seems to always leave flags empty..so no indication of pitch
                        // or linear size. And - to cap it all off - they leave pitchOrLinearSize as *zero*. Zero??? If
                        // we get this bizarre set of inputs, we just go 'screw it' and compute row pitch ourselves,
                        // making sure we DWORD align it (if that code path is enabled).
                        rowPitch = ((int)m_header.m_width * srcPixelSize);

            #if	APPLY_PITCH_ALIGNMENT
                    rowPitch = ( ( ( int )rowPitch + 3 ) & ( ~3 ) );
            #endif	// APPLY_PITCH_ALIGNMENT
                    }

                //				System.Diagnostics.Debug.WriteLine( "Image width : " + m_header.m_width + ", rowPitch = " + rowPitch );

                // Ok.. now, we need to allocate room for the bytes to read in from.. it's rowPitch bytes * height
                byte[] readPixelData = new byte[rowPitch * m_header.m_height];
                input.Read(readPixelData, 0, readPixelData.GetLength(0));

                // We now need space for the real pixel data.. that's width * height * 4..
                m_pixelData = new byte[m_header.m_width * m_header.m_height * 4];

                // And now we have the arduous task of filling that up with stuff..
                for (int destY = 0; destY < (int)m_header.m_height; destY++)
                {
                    for (int destX = 0; destX < (int)m_header.m_width; destX++)
                    {
                        // Compute source pixel offset
                        int srcPixelOffset = (destY * rowPitch) + (destX * srcPixelSize);

                        // Read our pixel
                        uint pixelColour = 0;
                        uint pixelRed = 0;
                        uint pixelGreen = 0;
                        uint pixelBlue = 0;
                        uint pixelAlpha = 0;

                        // Build our pixel colour as a DWORD
                        for (int loop = 0; loop < srcPixelSize; loop++)
                        {
                            pixelColour |= (uint)(readPixelData[srcPixelOffset + loop] << (8 * loop));
                        }

                        if (fileFormat == DdsFileFormat.DDS_FORMAT_A8R8G8B8)
                        {
                            pixelAlpha = (pixelColour >> 24) & 0xff;
                            pixelRed = (pixelColour >> 16) & 0xff;
                            pixelGreen = (pixelColour >> 8) & 0xff;
                            pixelBlue = (pixelColour >> 0) & 0xff;
                        }
                        else
                            if (fileFormat == DdsFileFormat.DDS_FORMAT_X8R8G8B8)
                            {
                                pixelAlpha = 0xff;
                                pixelRed = (pixelColour >> 16) & 0xff;
                                pixelGreen = (pixelColour >> 8) & 0xff;
                                pixelBlue = (pixelColour >> 0) & 0xff;
                            }
                            else
                                if (fileFormat == DdsFileFormat.DDS_FORMAT_A8B8G8R8)
                                {
                                    pixelAlpha = (pixelColour >> 24) & 0xff;
                                    pixelRed = (pixelColour >> 0) & 0xff;
                                    pixelGreen = (pixelColour >> 8) & 0xff;
                                    pixelBlue = (pixelColour >> 16) & 0xff;
                                }
                                else
                                    if (fileFormat == DdsFileFormat.DDS_FORMAT_X8B8G8R8)
                                    {
                                        pixelAlpha = 0xff;
                                        pixelRed = (pixelColour >> 0) & 0xff;
                                        pixelGreen = (pixelColour >> 8) & 0xff;
                                        pixelBlue = (pixelColour >> 16) & 0xff;
                                    }
                                    else
                                        if (fileFormat == DdsFileFormat.DDS_FORMAT_A1R5G5B5)
                                        {
                                            pixelAlpha = (pixelColour >> 15) * 0xff;
                                            pixelRed = (pixelColour >> 10) & 0x1f;
                                            pixelGreen = (pixelColour >> 5) & 0x1f;
                                            pixelBlue = (pixelColour >> 0) & 0x1f;

                                            pixelRed = (pixelRed << 3) | (pixelRed >> 2);
                                            pixelGreen = (pixelGreen << 3) | (pixelGreen >> 2);
                                            pixelBlue = (pixelBlue << 3) | (pixelBlue >> 2);
                                        }
                                        else
                                            if (fileFormat == DdsFileFormat.DDS_FORMAT_A4R4G4B4)
                                            {
                                                pixelAlpha = (pixelColour >> 12) & 0xff;
                                                pixelRed = (pixelColour >> 8) & 0x0f;
                                                pixelGreen = (pixelColour >> 4) & 0x0f;
                                                pixelBlue = (pixelColour >> 0) & 0x0f;

                                                pixelAlpha = (pixelAlpha << 4) | (pixelAlpha >> 0);
                                                pixelRed = (pixelRed << 4) | (pixelRed >> 0);
                                                pixelGreen = (pixelGreen << 4) | (pixelGreen >> 0);
                                                pixelBlue = (pixelBlue << 4) | (pixelBlue >> 0);
                                            }
                                            else
                                                if (fileFormat == DdsFileFormat.DDS_FORMAT_R8G8B8)
                                                {
                                                    pixelAlpha = 0xff;
                                                    pixelRed = (pixelColour >> 16) & 0xff;
                                                    pixelGreen = (pixelColour >> 8) & 0xff;
                                                    pixelBlue = (pixelColour >> 0) & 0xff;
                                                }
                                                else
                                                    if (fileFormat == DdsFileFormat.DDS_FORMAT_R5G6B5)
                                                    {
                                                        pixelAlpha = 0xff;
                                                        pixelRed = (pixelColour >> 11) & 0x1f;
                                                        pixelGreen = (pixelColour >> 5) & 0x3f;
                                                        pixelBlue = (pixelColour >> 0) & 0x1f;

                                                        pixelRed = (pixelRed << 3) | (pixelRed >> 2);
                                                        pixelGreen = (pixelGreen << 2) | (pixelGreen >> 4);
                                                        pixelBlue = (pixelBlue << 3) | (pixelBlue >> 2);
                                                    }

                        // Write the colours away..
                        int destPixelOffset = (destY * (int)m_header.m_width * 4) + (destX * 4);
                        m_pixelData[destPixelOffset + 0] = (byte)pixelRed;
                        m_pixelData[destPixelOffset + 1] = (byte)pixelGreen;
                        m_pixelData[destPixelOffset + 2] = (byte)pixelBlue;
                        m_pixelData[destPixelOffset + 3] = (byte)pixelAlpha;
                    }
                }

            }
        }
Example #22
0
        public void Save(Stream output, Surface surface, DdsFileFormat fileFormat, DdsCompressorType compressorType, DdsErrorMetric errorMetric, bool generateMipMaps, ResamplingAlgorithm mipMapResamplingAlgorithm, bool weightColorByAlpha, ProgressEventHandler progressCallback)
        {
            int  num21;
            int  num      = 0;
            bool flag     = ((fileFormat == DdsFileFormat.DDS_FORMAT_DXT1) || (fileFormat == DdsFileFormat.DDS_FORMAT_DXT3)) || (fileFormat == DdsFileFormat.DDS_FORMAT_DXT5);
            int  num2     = 1;
            int  mipWidth = surface.Width;
            int  height   = surface.Height;

            if (generateMipMaps)
            {
                while ((mipWidth > 1) || (height > 1))
                {
                    num2++;
                    mipWidth /= 2;
                    height   /= 2;
                }
            }
            this.m_header.m_size        = this.m_header.Size();
            this.m_header.m_headerFlags = 0x1007;
            if (flag)
            {
                this.m_header.m_headerFlags |= 0x80000;
            }
            else
            {
                this.m_header.m_headerFlags |= 8;
            }
            if (num2 > 1)
            {
                this.m_header.m_headerFlags |= 0x20000;
            }
            this.m_header.m_height = (uint)surface.Height;
            this.m_header.m_width  = (uint)surface.Width;
            if (flag)
            {
                int num5 = ((surface.Width + 3) / 4) * ((surface.Height + 3) / 4);
                int num6 = (fileFormat == DdsFileFormat.DDS_FORMAT_DXT1) ? 8 : 0x10;
                this.m_header.m_pitchOrLinearSize = (uint)(num5 * num6);
            }
            else
            {
                switch (fileFormat)
                {
                case DdsFileFormat.DDS_FORMAT_A8R8G8B8:
                case DdsFileFormat.DDS_FORMAT_X8R8G8B8:
                case DdsFileFormat.DDS_FORMAT_A8B8G8R8:
                case DdsFileFormat.DDS_FORMAT_X8B8G8R8:
                    num = 4;
                    break;

                case DdsFileFormat.DDS_FORMAT_A1R5G5B5:
                case DdsFileFormat.DDS_FORMAT_A4R4G4B4:
                case DdsFileFormat.DDS_FORMAT_R5G6B5:
                    num = 2;
                    break;

                case DdsFileFormat.DDS_FORMAT_R8G8B8:
                    num = 3;
                    break;
                }
                this.m_header.m_pitchOrLinearSize = (uint)(this.m_header.m_width * num);
            }
            this.m_header.m_depth        = 0;
            this.m_header.m_mipMapCount  = (num2 == 1) ? 0 : ((uint)num2);
            this.m_header.m_reserved1_0  = 0;
            this.m_header.m_reserved1_1  = 0;
            this.m_header.m_reserved1_2  = 0;
            this.m_header.m_reserved1_3  = 0;
            this.m_header.m_reserved1_4  = 0;
            this.m_header.m_reserved1_5  = 0;
            this.m_header.m_reserved1_6  = 0;
            this.m_header.m_reserved1_7  = 0;
            this.m_header.m_reserved1_8  = 0;
            this.m_header.m_reserved1_9  = 0;
            this.m_header.m_reserved1_10 = 0;
            this.m_header.m_pixelFormat.Initialise(fileFormat);
            this.m_header.m_surfaceFlags = 0x1000;
            if (num2 > 1)
            {
                this.m_header.m_surfaceFlags |= 0x400008;
            }
            this.m_header.m_cubemapFlags = 0;
            this.m_header.m_reserved2_0  = 0;
            this.m_header.m_reserved2_1  = 0;
            this.m_header.m_reserved2_2  = 0;
            output.WriteUInt32(0x20534444);
            this.m_header.Write(output);
            int squishFlags = this.GetSquishFlags(fileFormat, compressorType, errorMetric, weightColorByAlpha);

            mipWidth = surface.Width;
            height   = surface.Height;
            SizeInt32[] numArray        = new SizeInt32[num2];
            int[]       numArray2       = new int[num2];
            int[]       pixelsCompleted = new int[num2];
            long        totalPixels     = 0L;

            for (int i = 0; i < num2; i++)
            {
                SizeInt32 num8 = new SizeInt32((mipWidth > 0) ? mipWidth : 1, (height > 0) ? height : 1);
                numArray[i] = num8;
                int num9 = num8.Width * num8.Height;
                numArray2[i] = num9;
                if (i == 0)
                {
                    pixelsCompleted[i] = 0;
                }
                else
                {
                    pixelsCompleted[i] = pixelsCompleted[i - 1] + numArray2[i - 1];
                }
                totalPixels += num9;
                mipWidth    /= 2;
                height      /= 2;
            }
            mipWidth = surface.Width;
            height   = surface.Height;
            for (int mipLoop = 0; mipLoop < num2; mipLoop = num21 + 1)
            {
                byte[]    buffer;
                SizeInt32 size     = numArray[mipLoop];
                Surface   surface2 = new Surface(size);
                if (mipLoop == 0)
                {
                    surface2 = surface;
                }
                else
                {
                    IRenderer <ColorBgra> renderer;
                    SizeInt32             newSize = surface2.Size <ColorBgra>();
                    switch (mipMapResamplingAlgorithm)
                    {
                    case ResamplingAlgorithm.NearestNeighbor:
                        renderer = surface.ResizeNearestNeighbor(newSize);
                        break;

                    case ResamplingAlgorithm.Bilinear:
                        renderer = surface.ResizeBilinear(newSize);
                        break;

                    case ResamplingAlgorithm.Bicubic:
                        renderer = surface.ResizeBicubic(newSize);
                        break;

                    case ResamplingAlgorithm.SuperSampling:
                        renderer = surface.ResizeSuperSampling(newSize);
                        break;

                    case ResamplingAlgorithm.Fant:
                        renderer = surface.ResizeFant(newSize);
                        break;

                    default:
                        throw ExceptionUtil.InvalidEnumArgumentException <ResamplingAlgorithm>(mipMapResamplingAlgorithm, "mipMapResamplingAlgorithm");
                    }
                    renderer.Render <ColorBgra>(surface2);
                }
                DdsSquish.ProgressFn fn = delegate(int workDone, int workTotal) {
                    long   num  = workDone * mipWidth;
                    long   num2 = pixelsCompleted[mipLoop];
                    double num3 = (num + num2) / ((double)totalPixels);
                    progressCallback(this, new ProgressEventArgs(DoubleUtil.Clamp(100.0 * num3, 0.0, 100.0)));
                };
                if ((fileFormat >= DdsFileFormat.DDS_FORMAT_DXT1) && (fileFormat <= DdsFileFormat.DDS_FORMAT_DXT5))
                {
                    buffer = DdsSquish.CompressImage(surface2, squishFlags, (progressCallback == null) ? null : fn);
                }
                else
                {
                    int num12 = num * surface2.Width;
                    buffer = new byte[num12 * surface2.Height];
                    buffer.Initialize();
                    for (int j = 0; j < surface2.Height; j++)
                    {
                        for (int k = 0; k < surface2.Width; k++)
                        {
                            ColorBgra point = surface2.GetPoint(k, j);
                            uint      num15 = 0;
                            switch (fileFormat)
                            {
                            case DdsFileFormat.DDS_FORMAT_A8R8G8B8:
                                num15 = (uint)((((point.A << 0x18) | (point.R << 0x10)) | (point.G << 8)) | point.B);
                                break;

                            case DdsFileFormat.DDS_FORMAT_X8R8G8B8:
                                num15 = (uint)(((point.R << 0x10) | (point.G << 8)) | point.B);
                                break;

                            case DdsFileFormat.DDS_FORMAT_A8B8G8R8:
                                num15 = (uint)((((point.A << 0x18) | (point.B << 0x10)) | (point.G << 8)) | point.R);
                                break;

                            case DdsFileFormat.DDS_FORMAT_X8B8G8R8:
                                num15 = (uint)(((point.B << 0x10) | (point.G << 8)) | point.R);
                                break;

                            case DdsFileFormat.DDS_FORMAT_A1R5G5B5:
                                num15 = (uint)((((((point.A != null) ? 1 : 0) << 15) | ((point.R >> 3) << 10)) | ((point.G >> 3) << 5)) | (point.B >> 3));
                                break;

                            case DdsFileFormat.DDS_FORMAT_A4R4G4B4:
                                num15 = (uint)(((((point.A >> 4) << 12) | ((point.R >> 4) << 8)) | ((point.G >> 4) << 4)) | (point.B >> 4));
                                break;

                            case DdsFileFormat.DDS_FORMAT_R8G8B8:
                                num15 = (uint)(((point.R << 0x10) | (point.G << 8)) | point.B);
                                break;

                            case DdsFileFormat.DDS_FORMAT_R5G6B5:
                                num15 = (uint)((((point.R >> 3) << 11) | ((point.G >> 2) << 5)) | (point.B >> 3));
                                break;
                            }
                            int num16 = (j * num12) + (k * num);
                            for (int m = 0; m < num; m++)
                            {
                                buffer[num16 + m] = (byte)((num15 >> (8 * m)) & 0xff);
                            }
                        }
                        if (progressCallback != null)
                        {
                            long   num18 = (j + 1) * mipWidth;
                            long   num19 = pixelsCompleted[mipLoop];
                            double num20 = (num18 + num19) / ((double)totalPixels);
                            progressCallback(this, new ProgressEventArgs(100.0 * num20));
                        }
                    }
                }
                output.Write(buffer, 0, buffer.GetLength(0));
                mipWidth /= 2;
                height   /= 2;
                num21     = mipLoop;
            }
        }
 private static UInt32 GetMipMapOffset(DdsFileFormat fourcc, int width, int height, int mipmaps, int mipmapno, bool mipmapreversed)
 {
     UInt32 offset = 0;
     if (mipmapreversed)
     {
         for (int loop = mipmaps - 1; loop > mipmapno; loop--)
         {
             offset += GetMipMapSize(fourcc, width, height, mipmaps, loop);
         }
     }
     else
     {
         for (int loop = mipmapno; loop > 0; loop--)
         {
             offset += GetMipMapSize(fourcc, width, height, mipmaps, loop - 1);
         }
     }
     return offset;
 }
        private static byte[] DecodeTextureData(Stream file, DdsFileFormat fourcc, int width, int height, int mipmaps, int mipmapno, bool mipmapreversed)
        {
            UInt32 start = GetMipMapOffset(fourcc, width, height, mipmaps, mipmapno, mipmapreversed);
            UInt32 size = GetMipMapSize(fourcc, width, height, mipmaps, mipmapno);

            //if (input.Length == 0) return null;
            if (size == 0 || size + start + file.Position > file.Length)
                return null;

            width = (width + (1 << mipmapno) - 1) >> mipmapno;
            height = (height + (1 << mipmapno) - 1) >> mipmapno;

            file.Seek(start, System.IO.SeekOrigin.Current);
            byte[] data = new byte[size];
            file.Read(data, 0, (int)size);

            byte[] pixeldata = new byte[width * height * 4];
            //pixeldata[0] = 0x42;
            //pixeldata[1] = 0x4d;
            //BitConverter.GetBytes(pixeldata.Length).CopyTo(pixeldata, 2);
            //pixeldata[10] = 0x36;
            //pixeldata[14] = 0x28;
            //BitConverter.GetBytes(width).CopyTo(pixeldata, 18);
            //BitConverter.GetBytes(height).CopyTo(pixeldata, 22);
            //pixeldata[26] = 1;
            //pixeldata[28] = 32;
            //BitConverter.GetBytes(width * height * 4).CopyTo(pixeldata, 0);

            switch (fourcc)
            {
                case DdsFileFormat.DDS_FORMAT_ATI1:
                    DecodeATI1Texture(pixeldata, 0, width, height, data);
                    break;
                case DdsFileFormat.DDS_FORMAT_ATI2:
                    DecodeATI2Texture(pixeldata, 0, width, height, data);
                    break;
                case DdsFileFormat.DDS_FORMAT_DXT1:
                    DecodeDXT1Texture(pixeldata, 0, width, height, data);
                    break;
                case DdsFileFormat.DDS_FORMAT_DXT5:
                    DecodeDXT5Texture(pixeldata, 0, width, height, data);
                    break;
            }

            //System.IO.MemoryStream ms = new System.IO.MemoryStream(pixeldata);
            //using (ms)
            //{
            //    return new Bitmap(Image.FromStream(ms));
            //}
            return pixeldata;
        }
Example #25
0
 public DdsFileFormatSetting(string name, DdsFileFormat fileFormat)
 {
     Name          = name;
     DdsFileFormat = fileFormat;
 }
 private static string GetUnsupportedFormatMessage(DdsFileFormat format)
 {
     return(format.ToString() + " is not a supported pixel format.");
 }
Example #27
0
 public static void DDS_To_DDS(string From_DDS_File, string To_DDS_File, DdsFileFormat Format)
 {
     System.IO.FileStream fileStream = new System.IO.FileStream(To_DDS_File, System.IO.FileMode.Create);
     DdsFile.Save(fileStream, Format, DdsErrorMetric.Perceptual, BC7CompressionMode.Slow, false, false, ResamplingAlgorithm.Bilinear, Load(From_DDS_File), null);
     fileStream.Close();
 }
 private static UInt32 GetMipMapSize(DdsFileFormat fourcc, int width, int height, int mipmaps, int mipmapno)
 {
     width = (width + (1 << mipmapno) - 1) >> mipmapno;
     height = (height + (1 << mipmapno) - 1) >> mipmapno;
     switch (fourcc)
     {
         case DdsFileFormat.DDS_FORMAT_DXT1:
             return (UInt32)(((width + 3) / 4) * ((height + 3) / 4)) * 8;
         case DdsFileFormat.DDS_FORMAT_DXT5:
             return (UInt32)(((width + 3) / 4) * ((height + 3) / 4)) * 16;
         case DdsFileFormat.DDS_FORMAT_ATI1:
             return (UInt32)(((width + 3) / 4) * ((height + 3) / 4)) * 8;
         case DdsFileFormat.DDS_FORMAT_ATI2:
             return (UInt32)(((width + 3) / 4) * ((height + 3) / 4)) * 16;
         default:
             return 0;
     }
 }
Example #29
0
        /*
         * public void Save(System.IO.Stream output, Surface surface, DdsSaveConfigToken ddsToken, ProgressEventHandler progressCallback) {
         * // For non-compressed textures, we need pixel width.
         * int pixelWidth = 0;
         *
         * // Identify if we're a compressed image
         * bool isCompressed = ((ddsToken.m_fileFormat == DdsFileFormat.DDS_FORMAT_DXT1) ||
         *            (ddsToken.m_fileFormat == DdsFileFormat.DDS_FORMAT_DXT3) ||
         *            (ddsToken.m_fileFormat == DdsFileFormat.DDS_FORMAT_DXT5));
         *
         * // Compute mip map count..
         * int mipCount = 1;
         * int mipWidth = surface.Width;
         * int mipHeight = surface.Height;
         *
         * if (ddsToken.m_generateMipMaps) {
         *  // This breaks!
         *
         *  while ((mipWidth > 1) || (mipHeight > 1)) {
         *    mipCount++;
         *    mipWidth /= 2;
         *    mipHeight /= 2;
         *  }
         * }
         *
         * // Populate bulk of our DdsHeader
         * m_header.m_size = m_header.Size();
         * m_header.m_headerFlags = (uint)(DdsHeader.HeaderFlags.DDS_HEADER_FLAGS_TEXTURE);
         *
         * if (isCompressed)
         *  m_header.m_headerFlags |= (uint)(DdsHeader.HeaderFlags.DDS_HEADER_FLAGS_LINEARSIZE);
         * else
         *  m_header.m_headerFlags |= (uint)(DdsHeader.HeaderFlags.DDS_HEADER_FLAGS_PITCH);
         *
         * if (mipCount > 1)
         *  m_header.m_headerFlags |= (uint)(DdsHeader.HeaderFlags.DDS_HEADER_FLAGS_MIPMAP);
         *
         * m_header.m_height = (uint)surface.Height;
         * m_header.m_width = (uint)surface.Width;
         *
         * if (isCompressed) {
         *  // Compresssed textures have the linear flag set.So pitchOrLinearSize
         *  // needs to contain the entire size of the DXT block.
         *  int blockCount = ((surface.Width + 3) / 4) * ((surface.Height + 3) / 4);
         *  int blockSize = (ddsToken.m_fileFormat == 0) ? 8 : 16;
         *  m_header.m_pitchOrLinearSize = (uint)(blockCount * blockSize);
         * }
         * else {
         *  // Non-compressed textures have the pitch flag set. So pitchOrLinearSize
         *  // needs to contain the row pitch of the main image. DWORD aligned too.
         *  switch (ddsToken.m_fileFormat) {
         *  case DdsFileFormat.DDS_FORMAT_A8R8G8B8:
         *  case DdsFileFormat.DDS_FORMAT_X8R8G8B8:
         *  case DdsFileFormat.DDS_FORMAT_A8B8G8R8:
         *  case DdsFileFormat.DDS_FORMAT_X8B8G8R8:
         *    pixelWidth = 4;    // 32bpp
         *    break;
         *
         *  case DdsFileFormat.DDS_FORMAT_A1R5G5B5:
         *  case DdsFileFormat.DDS_FORMAT_A4R4G4B4:
         *  case DdsFileFormat.DDS_FORMAT_R5G6B5:
         *    pixelWidth = 2;    // 16bpp
         *    break;
         *
         *  case DdsFileFormat.DDS_FORMAT_R8G8B8:
         *    pixelWidth = 3;    // 24bpp
         *    break;
         *  }
         *
         *  // Compute row pitch
         *  m_header.m_pitchOrLinearSize = (uint)((int)m_header.m_width * pixelWidth);
         *
         #if  APPLY_PITCH_ALIGNMENT
         *  // Align to DWORD, if we need to.. (see notes about pitch alignment all over this code)
         *  m_header.m_pitchOrLinearSize = ( uint )( ( ( int )m_header.m_pitchOrLinearSize + 3 ) & ( ~3 ) );
         #endif  //APPLY_PITCH_ALIGNMENT
         * }
         *
         * m_header.m_depth = 0;
         * m_header.m_mipMapCount = (mipCount == 1) ? 0 : (uint)mipCount;
         * m_header.m_reserved1_0 = 0;
         * m_header.m_reserved1_1 = 0;
         * m_header.m_reserved1_2 = 0;
         * m_header.m_reserved1_3 = 0;
         * m_header.m_reserved1_4 = 0;
         * m_header.m_reserved1_5 = 0;
         * m_header.m_reserved1_6 = 0;
         * m_header.m_reserved1_7 = 0;
         * m_header.m_reserved1_8 = 0;
         * m_header.m_reserved1_9 = 0;
         * m_header.m_reserved1_10 = 0;
         *
         * // Populate our DdsPixelFormat object
         * m_header.m_pixelFormat.Initialise(ddsToken.m_fileFormat);
         *
         * // Populate miscellanous header flags
         * m_header.m_surfaceFlags = (uint)DdsHeader.SurfaceFlags.DDS_SURFACE_FLAGS_TEXTURE;
         *
         * if (mipCount > 1)
         *  m_header.m_surfaceFlags |= (uint)DdsHeader.SurfaceFlags.DDS_SURFACE_FLAGS_MIPMAP;
         *
         * m_header.m_cubemapFlags = 0;
         * m_header.m_reserved2_0 = 0;
         * m_header.m_reserved2_1 = 0;
         * m_header.m_reserved2_2 = 0;
         *
         * // Write out our DDS tag
         * Utility.WriteUInt32(output, 0x20534444); // 'DDS '
         *
         * // Write out the header
         * m_header.Write(output);
         *
         * int squishFlags = ddsToken.GetSquishFlags();
         *
         * // Our output data array will be sized as necessary
         * byte[] outputData;
         *
         * // Reset our mip width & height variables...
         * mipWidth = surface.Width;
         * mipHeight = surface.Height;
         *
         * // Figure out how much total work each mip map is
         * Size[] writeSizes = new Size[mipCount];
         * int[] mipPixels = new int[mipCount];
         * int[] pixelsCompleted = new int[mipCount]; // # pixels completed once we have reached this mip
         * long totalPixels = 0;
         * for (int mipLoop = 0; mipLoop < mipCount; mipLoop++) {
         *  Size writeSize = new Size((mipWidth > 0) ? mipWidth : 1, (mipHeight > 0) ? mipHeight : 1);
         *  writeSizes[mipLoop] = writeSize;
         *
         *  int thisMipPixels = writeSize.Width * writeSize.Height;
         *  mipPixels[mipLoop] = thisMipPixels;
         *
         *  if (mipLoop == 0) {
         *    pixelsCompleted[mipLoop] = 0;
         *  }
         *  else {
         *    pixelsCompleted[mipLoop] = pixelsCompleted[mipLoop - 1] + mipPixels[mipLoop - 1];
         *  }
         *
         *  totalPixels += thisMipPixels;
         *  mipWidth /= 2;
         *  mipHeight /= 2;
         * }
         *
         * mipWidth = surface.Width;
         * mipHeight = surface.Height;
         *
         * for (int mipLoop = 0; mipLoop < mipCount; mipLoop++) {
         *  Size writeSize = writeSizes[mipLoop];
         *  Surface writeSurface = new Surface(writeSize);
         *
         *  if (mipLoop == 0) {
         *    // No point resampling the first level.. it's got exactly what we want.
         *    writeSurface = surface;
         *  }
         *  else {
         *    // I'd love to have a UI component to select what kind of resampling, but
         *    // there's hardly any space for custom UI stuff in the Save Dialog. And I'm
         *    // not having any scrollbars in there..!
         *    // Also, note that each mip level is formed from the main level, to reduce
         *    // compounded errors when generating mips.
         *    writeSurface.SuperSamplingFitSurface(surface);
         *  }
         *
         *  DdsSquish.ProgressFn progressFn =
         *      delegate(int workDone, int workTotal) {
         *        long thisMipPixelsDone = workDone * (long)mipWidth;
         *        long previousMipsPixelsDone = pixelsCompleted[mipLoop];
         *        double progress = (double)((double)thisMipPixelsDone +
         * (double)previousMipsPixelsDone) / (double)totalPixels;
         *        progressCallback(this, new ProgressEventArgs(100.0 * progress));
         *      };
         *
         *  if ((ddsToken.m_fileFormat >= DdsFileFormat.DDS_FORMAT_DXT1) &&
         * (ddsToken.m_fileFormat <= DdsFileFormat.DDS_FORMAT_DXT5))
         *    outputData = DdsSquish.CompressImage(writeSurface, squishFlags,
         * (progressCallback == null) ? null : progressFn);
         *  else {
         *    int mipPitch = pixelWidth * writeSurface.Width;
         *
         *    // From the DDS documents I read, I'd expected the pitch of each mip level to be
         *    // DWORD aligned. As it happens, that's not the case. Re-aligning the pitch of
         *    // each level results in later mips getting sheared as the pitch is incorrect.
         *    // So, the following line is intentionally optional. Maybe the documentation
         *    // is referring to the pitch when accessing the mip directly.. who knows.
         *    //
         *    // Infact, all the talk of non-compressed textures having DWORD alignment of pitch
         *    // seems to be bollocks.. If I apply alignment, then they fail to load in 3rd Party
         *    // or Microsoft DDS viewing applications.
         *    //
         *
         #if  APPLY_PITCH_ALIGNMENT
         *    mipPitch = ( mipPitch + 3 ) & ( ~3 );
         #endif // APPLY_PITCH_ALIGNMENT
         *
         *    outputData = new byte[mipPitch * writeSurface.Height];
         *    outputData.Initialize();
         *
         *    for (int y = 0; y < writeSurface.Height; y++) {
         *      for (int x = 0; x < writeSurface.Width; x++) {
         *        // Get colour from surface
         *        ColorBgra pixelColour = writeSurface.GetPoint(x, y);
         *        uint pixelData = 0;
         *
         *        switch (ddsToken.m_fileFormat) {
         *        case DdsFileFormat.DDS_FORMAT_A8R8G8B8: {
         *            pixelData = ((uint)pixelColour.A << 24) |
         *                  ((uint)pixelColour.R << 16) |
         *                  ((uint)pixelColour.G << 8) |
         *                  ((uint)pixelColour.B << 0);
         *            break;
         *          }
         *
         *        case DdsFileFormat.DDS_FORMAT_X8R8G8B8: {
         *            pixelData = ((uint)pixelColour.R << 16) |
         *                  ((uint)pixelColour.G << 8) |
         *                  ((uint)pixelColour.B << 0);
         *            break;
         *          }
         *
         *        case DdsFileFormat.DDS_FORMAT_A8B8G8R8: {
         *            pixelData = ((uint)pixelColour.A << 24) |
         *                  ((uint)pixelColour.B << 16) |
         *                  ((uint)pixelColour.G << 8) |
         *                  ((uint)pixelColour.R << 0);
         *            break;
         *          }
         *
         *        case DdsFileFormat.DDS_FORMAT_X8B8G8R8: {
         *            pixelData = ((uint)pixelColour.B << 16) |
         *                  ((uint)pixelColour.G << 8) |
         *                  ((uint)pixelColour.R << 0);
         *            break;
         *          }
         *
         *        case DdsFileFormat.DDS_FORMAT_A1R5G5B5: {
         *            pixelData = ((uint)((pixelColour.A != 0) ? 1 : 0) << 15) |
         *                  ((uint)(pixelColour.R >> 3) << 10) |
         *                  ((uint)(pixelColour.G >> 3) << 5) |
         *                  ((uint)(pixelColour.B >> 3) << 0);
         *            break;
         *          }
         *
         *        case DdsFileFormat.DDS_FORMAT_A4R4G4B4: {
         *            pixelData = ((uint)(pixelColour.A >> 4) << 12) |
         *                  ((uint)(pixelColour.R >> 4) << 8) |
         *                  ((uint)(pixelColour.G >> 4) << 4) |
         *                  ((uint)(pixelColour.B >> 4) << 0);
         *            break;
         *          }
         *
         *        case DdsFileFormat.DDS_FORMAT_R8G8B8: {
         *            pixelData = ((uint)pixelColour.R << 16) |
         *                  ((uint)pixelColour.G << 8) |
         *                  ((uint)pixelColour.B << 0);
         *            break;
         *          }
         *
         *        case DdsFileFormat.DDS_FORMAT_R5G6B5: {
         *            pixelData = ((uint)(pixelColour.R >> 3) << 11) |
         *                  ((uint)(pixelColour.G >> 2) << 5) |
         *                  ((uint)(pixelColour.B >> 3) << 0);
         *            break;
         *          }
         *        }
         *
         *        // pixelData contains our target data.. so now set the pixel bytes
         *        int pixelOffset = (y * mipPitch) + (x * pixelWidth);
         *        for (int loop = 0; loop < pixelWidth; loop++) {
         *          outputData[pixelOffset + loop] = (byte)((pixelData >> (8 * loop)) & 0xff);
         *        }
         *      }
         *
         *      if (progressCallback != null) {
         *        long thisMipPixelsDone = (y + 1) * (long)mipWidth;
         *        long previousMipsPixelsDone = pixelsCompleted[mipLoop];
         *        double progress = (double)((double)thisMipPixelsDone +
         * (double)previousMipsPixelsDone) / (double)totalPixels;
         *        progressCallback(this, new ProgressEventArgs(100.0 * progress));
         *      }
         *    }
         *  }
         *
         *  // Write the data for this mip level out..
         *  output.Write(outputData, 0, outputData.GetLength(0));
         *
         *  mipWidth = mipWidth / 2;
         *  mipHeight = mipHeight / 2;
         * }
         * }*/

        public Bitmap Load(BinaryReader input)
        {
            // Read the DDS tag. If it's not right, then bail..
            UInt32 ddsTag = input.ReadUInt32();

            if (ddsTag != 0x20534444)
            {
                throw new FormatException("File does not appear to be a DDS image");
            }

            m_header.Read(input);

            if ((Header.PixelFormat.Flags &
                 (UInt32)PixelFormatFlags.DDS_FOURCC) != 0)
            {
                UInt32 squishFlags = 0;

                switch (Header.PixelFormat.FourCC)
                {
                case 0x31545844:
                    squishFlags = (UInt32)SquishFlags.Dxt1;
                    break;

                case 0x33545844:
                    squishFlags = (UInt32)SquishFlags.Dxt3;
                    break;

                case 0x35545844:
                    squishFlags = (UInt32)SquishFlags.Dxt5;
                    break;

                default:
                    throw new FormatException("File is not a supported DDS format");
                }

                // Compute size of compressed block area
                int blockCount = ((this.Width + 3) / 4) * ((this.Height + 3) / 4);
                int blockSize  = ((squishFlags & (UInt32)SquishFlags.Dxt1) != 0) ? 8 : 16;

                // Allocate room for compressed blocks, and read data into it.
                byte[] compressedBlocks = new byte[blockCount * blockSize];
                input.Read(compressedBlocks, 0, compressedBlocks.GetLength(0));

                // Now decompress..
                return(DdsSquish.DecompressImage(compressedBlocks,
                                                 this.Width, this.Height, (int)squishFlags));
            }
            else
            {
                // We can only deal with the non-DXT formats we know about..  this is a bit of a mess..
                // Sorry..
                DdsFileFormat fileFormat = DdsFileFormat.DDS_FORMAT_INVALID;

                if (
                    (this.Header.PixelFormat.Flags == (UInt32)PixelFormatFlags.DDS_RGBA) &&
                    (this.Header.PixelFormat.RgbBitCount == 0x20) &&
                    (this.Header.PixelFormat.BitMaskA == 0xff000000) &&
                    (this.Header.PixelFormat.BitMaskR == 0x00ff0000) &&
                    (this.Header.PixelFormat.BitMaskG == 0x0000ff00) &&
                    (this.Header.PixelFormat.BitMaskB == 0x000000ff))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_A8R8G8B8;
                }

                else if (
                    (this.Header.PixelFormat.Flags == (UInt32)PixelFormatFlags.DDS_RGB) &&
                    (this.Header.PixelFormat.RgbBitCount == 0x20) &&
                    (this.Header.PixelFormat.BitMaskA == 0x00000000) &&
                    (this.Header.PixelFormat.BitMaskR == 0x00ff0000) &&
                    (this.Header.PixelFormat.BitMaskG == 0x0000ff00) &&
                    (this.Header.PixelFormat.BitMaskB == 0x000000ff))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_X8R8G8B8;
                }

                else if (
                    (this.Header.PixelFormat.Flags == (UInt32)PixelFormatFlags.DDS_RGBA) &&
                    (this.Header.PixelFormat.RgbBitCount == 0x20) &&
                    (this.Header.PixelFormat.BitMaskA == 0xff000000) &&
                    (this.Header.PixelFormat.BitMaskR == 0x000000ff) &&
                    (this.Header.PixelFormat.BitMaskG == 0x0000ff00) &&
                    (this.Header.PixelFormat.BitMaskB == 0x00ff0000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_A8B8G8R8;
                }

                else if (
                    (this.Header.PixelFormat.Flags == (UInt32)PixelFormatFlags.DDS_RGB) &&
                    (this.Header.PixelFormat.RgbBitCount == 0x20) &&
                    (this.Header.PixelFormat.BitMaskA == 0x00000000) &&
                    (this.Header.PixelFormat.BitMaskR == 0x000000ff) &&
                    (this.Header.PixelFormat.BitMaskG == 0x0000ff00) &&
                    (this.Header.PixelFormat.BitMaskB == 0x00ff0000))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_X8B8G8R8;
                }

                else if (
                    (this.Header.PixelFormat.Flags == (UInt32)PixelFormatFlags.DDS_RGBA) &&
                    (this.Header.PixelFormat.RgbBitCount == 0x10) &&
                    (this.Header.PixelFormat.BitMaskA == 0x00008000) &&
                    (this.Header.PixelFormat.BitMaskR == 0x00007c00) &&
                    (this.Header.PixelFormat.BitMaskG == 0x000003e0) &&
                    (this.Header.PixelFormat.BitMaskB == 0x0000001f))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_A1R5G5B5;
                }

                else if (
                    (this.Header.PixelFormat.Flags == (UInt32)PixelFormatFlags.DDS_RGBA) &&
                    (this.Header.PixelFormat.RgbBitCount == 0x10) &&
                    (this.Header.PixelFormat.BitMaskA == 0x0000f000) &&
                    (this.Header.PixelFormat.BitMaskR == 0x00000f00) &&
                    (this.Header.PixelFormat.BitMaskG == 0x000000f0) &&
                    (this.Header.PixelFormat.BitMaskB == 0x0000000f))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_A4R4G4B4;
                }

                else if (
                    (this.Header.PixelFormat.Flags == (UInt32)PixelFormatFlags.DDS_RGB) &&
                    (this.Header.PixelFormat.RgbBitCount == 0x18) &&
                    (this.Header.PixelFormat.BitMaskA == 0x00000000) &&
                    (this.Header.PixelFormat.BitMaskR == 0x00ff0000) &&
                    (this.Header.PixelFormat.BitMaskG == 0x0000ff00) &&
                    (this.Header.PixelFormat.BitMaskB == 0x000000ff))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_R8G8B8;
                }

                else if (
                    (this.Header.PixelFormat.Flags == (UInt32)PixelFormatFlags.DDS_RGB) &&
                    (this.Header.PixelFormat.RgbBitCount == 0x10) &&
                    (this.Header.PixelFormat.BitMaskA == 0x00000000) &&
                    (this.Header.PixelFormat.BitMaskR == 0x0000f800) &&
                    (this.Header.PixelFormat.BitMaskG == 0x000007e0) &&
                    (this.Header.PixelFormat.BitMaskB == 0x0000001f))
                {
                    fileFormat = DdsFileFormat.DDS_FORMAT_R5G6B5;
                }

                // If fileFormat is still invalid, then it's an unsupported format.
                if (fileFormat == DdsFileFormat.DDS_FORMAT_INVALID)
                {
                    throw new FormatException("File is not a supported DDS format");
                }

                // Size of a source pixel, in bytes
                UInt32 srcPixelSize = ((UInt32)this.Header.PixelFormat.RgbBitCount / 8);

                // We need the pitch for a row, so we can allocate enough memory for the load.
                UInt32 rowPitch = 0;

                if ((this.Header.Flags & (UInt32)HeaderFlags.DDS_HEADER_FLAGS_PITCH) != 0)
                {
                    // Pitch specified.. so we can use directly
                    rowPitch = (UInt32)this.Header.PitchOrLinearSize;
                }
                else
                if ((this.Header.Flags & (int)HeaderFlags.DDS_HEADER_FLAGS_LINEARSIZE) != 0)
                {
                    // Linear size specified. compute row pitch. Of course, this should never happen
                    // as linear size is *supposed* to be for compressed textures. But Microsoft don't
                    // always play by the rules when it comes to DDS output.
                    rowPitch = (UInt32)this.Header.PitchOrLinearSize / this.Header.Height;
                }
                else
                {
                    // Another case of Microsoft not obeying their standard is the
                    // 'Convert to..' shell extension that ships in the DirectX SDK.
                    // Seems to always leave flags empty..so no indication of pitch
                    // or linear size. And - to cap it all off - they leave
                    // pitchOrLinearSize as *zero*. Zero??? If we get this bizarre set
                    // of inputs, we just go 'screw it' and compute row pitch
                    // ourselves, making sure we DWORD align it (if that code path is
                    // enabled).
                    rowPitch = (this.Header.Width * srcPixelSize);

            #if APPLY_PITCH_ALIGNMENT
                    rowPitch = ((( int )rowPitch + 3) & (~3));
            #endif
                }

                // Ok.. now, we need to allocate room for the bytes to read in from.
                // It's rowPitch bytes * height
                byte[] readPixelData = new byte[rowPitch * this.Header.Height];
                input.Read(readPixelData, 0, readPixelData.GetLength(0));

                // We now need space for the real pixel data.
                byte[] pixelData = new byte[this.Header.Width * this.Header.Height * 4];

                // And now we have the arduous task of filling that up with stuff..
                for (UInt32 destY = 0; destY < this.Header.Height; destY++)
                {
                    for (UInt32 destX = 0; destX < this.Header.Width; destX++)
                    {
                        // Compute source pixel offset
                        UInt32 srcPixelOffset = (destY * rowPitch) + (destX * srcPixelSize);

                        // Read our pixel
                        UInt32 pixelColor = 0;
                        UInt32 pixelR     = 0;
                        UInt32 pixelG     = 0;
                        UInt32 pixelB     = 0;
                        UInt32 pixelA     = 0;

                        // Build our pixel colour as a DWORD
                        for (int loop = 0; loop < srcPixelSize; loop++)
                        {
                            pixelColor |= (uint)(readPixelData[srcPixelOffset + loop] << (8 * loop));
                        }

                        switch (fileFormat)
                        {
                        case DdsFileFormat.DDS_FORMAT_A8R8G8B8:
                            pixelA = (pixelColor >> 0x18) & 0xff;
                            pixelR = (pixelColor >> 0x10) & 0xff;
                            pixelG = (pixelColor >> 0x08) & 0xff;
                            pixelB = pixelColor & 0xff;
                            break;

                        case DdsFileFormat.DDS_FORMAT_X8R8G8B8:
                            pixelA = 0xff;
                            pixelR = (pixelColor >> 0x10) & 0xff;
                            pixelG = (pixelColor >> 0x08) & 0xff;
                            pixelB = pixelColor & 0xff;
                            break;

                        case DdsFileFormat.DDS_FORMAT_A8B8G8R8:
                            pixelA = (pixelColor >> 0x18) & 0xff;
                            pixelR = pixelColor & 0xff;
                            pixelG = (pixelColor >> 0x08) & 0xff;
                            pixelB = (pixelColor >> 0x10) & 0xff;
                            break;

                        case DdsFileFormat.DDS_FORMAT_X8B8G8R8:
                            pixelA = 0xff;
                            pixelR = pixelColor & 0xff;
                            pixelG = (pixelColor >> 0x08) & 0xff;
                            pixelB = (pixelColor >> 0x10) & 0xff;
                            break;

                        case DdsFileFormat.DDS_FORMAT_A1R5G5B5:
                            pixelA = (pixelColor >> 15) * 0xff;
                            pixelR = (pixelColor >> 10) & 0x1f;
                            pixelR = (pixelR << 3) | (pixelR >> 2);
                            pixelG = (pixelColor >> 5) & 0x1f;
                            pixelG = (pixelG << 3) | (pixelG >> 2);
                            pixelB = (pixelColor >> 0) & 0x1f;
                            pixelB = (pixelB << 3) | (pixelB >> 2);
                            break;

                        case DdsFileFormat.DDS_FORMAT_A4R4G4B4:
                            pixelA = (pixelColor >> 12) & 0xff;
                            pixelA = (pixelA << 4) | (pixelA >> 0);
                            pixelR = (pixelColor >> 8) & 0x0f;
                            pixelR = (pixelR << 4) | (pixelR >> 0);
                            pixelG = (pixelColor >> 4) & 0x0f;
                            pixelG = (pixelG << 4) | (pixelG >> 0);
                            pixelB = (pixelColor >> 0) & 0x0f;
                            pixelB = (pixelB << 4) | (pixelB >> 0);
                            break;

                        case DdsFileFormat.DDS_FORMAT_R8G8B8:
                            pixelA = 0xff;
                            pixelR = (pixelColor >> 0x10) & 0xff;
                            pixelG = (pixelColor >> 0x08) & 0xff;
                            pixelB = pixelColor & 0xff;
                            break;

                        case DdsFileFormat.DDS_FORMAT_R5G6B5:
                            pixelA = 0xff;
                            pixelR = (pixelColor >> 0x0b) & 0x1f;
                            pixelR = (pixelR << 0x03) | (pixelR >> 0x02);
                            pixelG = (pixelColor >> 0x05) & 0x3f;
                            pixelG = (pixelG << 0x02) | (pixelG >> 0x04);
                            pixelB = pixelColor & 0x1f;
                            pixelB = (pixelB << 0x03) | (pixelB >> 0x02);
                            break;
                        }

                        UInt32 destPixelOffset = (destY * this.Header.Width * 4) +
                                                 (destX * 4);
                        pixelData[destPixelOffset + 0] = (byte)pixelB;
                        pixelData[destPixelOffset + 1] = (byte)pixelG;
                        pixelData[destPixelOffset + 2] = (byte)pixelR;
                        pixelData[destPixelOffset + 3] = (byte)pixelA;
                    }
                }

                // Copy the pixel data to a new bitmap
                Bitmap bmp = new Bitmap(this.Width, this.Height,
                                        PixelFormat.Format32bppArgb);
                Rectangle  rect    = new Rectangle(0, 0, this.Width, this.Height);
                BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.WriteOnly,
                                                  bmp.PixelFormat);
                System.Runtime.InteropServices.Marshal.Copy(pixelData, 0,
                                                            bmpData.Scan0, this.Stride * this.Height);
                bmp.UnlockBits(bmpData);
                return(bmp);
            }
        }
Example #30
0
        public static void Save(
            IServiceProvider services,
            Document input,
            Stream output,
            DdsFileFormat format,
            DdsErrorMetric errorMetric,
            BC7CompressionMode compressionMode,
            bool cubeMap,
            bool generateMipmaps,
            ResamplingAlgorithm sampling,
            Surface scratchSurface,
            ProgressEventHandler progressCallback)
        {
            using (RenderArgs args = new RenderArgs(scratchSurface))
            {
                input.Render(args, true);
            }

            DdsNative.DdsProgressCallback ddsProgress = null;
            if (progressCallback != null)
            {
                ddsProgress = (UIntPtr done, UIntPtr total) =>
                {
                    double progress = (double)done.ToUInt64() / (double)total.ToUInt64();
                    try
                    {
                        progressCallback(null, new ProgressEventArgs(progress * 100.0, true));
                        return(true);
                    }
                    catch (OperationCanceledException)
                    {
                        return(false);
                    }
                };
            }

            int  width           = scratchSurface.Width;
            int  height          = scratchSurface.Height;
            int  arraySize       = 1;
            Size?cubeMapFaceSize = null;

            if (cubeMap && IsCrossedCubeMapSize(scratchSurface))
            {
                if (width > height)
                {
                    width  /= 4;
                    height /= 3;
                }
                else
                {
                    width  /= 3;
                    height /= 4;
                }
                arraySize       = 6;
                cubeMapFaceSize = new Size(width, height);
            }

            int  mipLevels = generateMipmaps ? GetMipCount(width, height) : 1;
            bool enableHardwareAcceleration = (bool)services.GetService <ISettingsService>().GetSetting(AppSettingPaths.UI.EnableHardwareAcceleration).Value;

            DdsNative.DDSSaveInfo info = new DdsNative.DDSSaveInfo
            {
                width                      = width,
                height                     = height,
                arraySize                  = arraySize,
                mipLevels                  = mipLevels,
                format                     = format,
                errorMetric                = errorMetric,
                compressionMode            = compressionMode,
                cubeMap                    = cubeMapFaceSize.HasValue,
                enableHardwareAcceleration = enableHardwareAcceleration
            };

            using (TextureCollection textures = GetTextures(scratchSurface, cubeMapFaceSize, mipLevels, sampling))
            {
                DdsNative.Save(info, textures, output, ddsProgress);
            }
        }
        public void Initialise( DdsFileFormat fileFormat )
        {
            m_size = Size();
            switch( fileFormat )
            {
                case	DdsFileFormat.DDS_FORMAT_DXT1:
                case	DdsFileFormat.DDS_FORMAT_DXT3:
                case	DdsFileFormat.DDS_FORMAT_DXT5:
                {
                    // DXT1/DXT3/DXT5
                    m_flags			= ( int )PixelFormatFlags.DDS_FOURCC;
                    m_rgbBitCount	=	0;
                    m_rBitMask		=	0;
                    m_gBitMask		=	0;
                    m_bBitMask		=	0;
                    m_aBitMask		=	0;
                    if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT1) { m_fourCC = 0x31545844; }//"DXT1"
                    if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT3) { m_fourCC = 0x33545844; } //"DXT1"
                    if (fileFormat == DdsFileFormat.DDS_FORMAT_DXT5) { m_fourCC = 0x35545844; } //"DXT1"
                    break;
                }

                case	DdsFileFormat.DDS_FORMAT_A8R8G8B8:
                {
                    m_flags			= ( int )PixelFormatFlags.DDS_RGB + (int)PixelFormatFlags.DDS_ALPHAPIXELS;
                    m_rgbBitCount	= 32;
                    m_fourCC		= 0;
                    m_rBitMask		= 0x00ff0000;
                    m_gBitMask		= 0x0000ff00;
                    m_bBitMask		= 0x000000ff;
                    m_aBitMask		= 0xff000000;
                    break;
                }

                case	DdsFileFormat.DDS_FORMAT_X8R8G8B8:
                {
                    m_flags			= ( int )PixelFormatFlags.DDS_RGB;
                    m_rgbBitCount	= 32;
                    m_fourCC		= 0;
                    m_rBitMask		= 0x00ff0000;
                    m_gBitMask		= 0x0000ff00;
                    m_bBitMask		= 0x000000ff;
                    m_aBitMask		= 0x00000000;
                    break;
                }

                case	DdsFileFormat.DDS_FORMAT_A8B8G8R8:
                {
                    m_flags			= ( int )PixelFormatFlags.DDS_RGB + (int)PixelFormatFlags.DDS_ALPHAPIXELS;
                    m_rgbBitCount	= 32;
                    m_fourCC		= 0;
                    m_rBitMask		= 0x000000ff;
                    m_gBitMask		= 0x0000ff00;
                    m_bBitMask		= 0x00ff0000;
                    m_aBitMask		= 0xff000000;
                    break;
                }

                case	DdsFileFormat.DDS_FORMAT_X8B8G8R8:
                {
                    m_flags			= ( int )PixelFormatFlags.DDS_RGB;
                    m_rgbBitCount	= 32;
                    m_fourCC		= 0;
                    m_rBitMask		= 0x000000ff;
                    m_gBitMask		= 0x0000ff00;
                    m_bBitMask		= 0x00ff0000;
                    m_aBitMask		= 0x00000000;
                    break;
                }

                case	DdsFileFormat.DDS_FORMAT_A1R5G5B5:
                {
                    m_flags			= ( int )PixelFormatFlags.DDS_RGB + (int)PixelFormatFlags.DDS_ALPHAPIXELS;
                    m_rgbBitCount	= 16;
                    m_fourCC		= 0;
                    m_rBitMask		= 0x00007c00;
                    m_gBitMask		= 0x000003e0;
                    m_bBitMask		= 0x0000001f;
                    m_aBitMask		= 0x00008000;
                    break;
                }

                case	DdsFileFormat.DDS_FORMAT_A4R4G4B4:
                {
                    m_flags			= ( int )PixelFormatFlags.DDS_RGB + (int)PixelFormatFlags.DDS_ALPHAPIXELS;
                    m_rgbBitCount	= 16;
                    m_fourCC		= 0;
                    m_rBitMask		= 0x00000f00;
                    m_gBitMask		= 0x000000f0;
                    m_bBitMask		= 0x0000000f;
                    m_aBitMask		= 0x0000f000;
                    break;
                }

                case	DdsFileFormat.DDS_FORMAT_R8G8B8:
                {
                    m_flags			= ( int )PixelFormatFlags.DDS_RGB;
                    m_fourCC		= 0;
                    m_rgbBitCount	= 24;
                    m_rBitMask		= 0x00ff0000;
                    m_gBitMask		= 0x0000ff00;
                    m_bBitMask		= 0x000000ff;
                    m_aBitMask		= 0x00000000;
                    break;
                }

                case	DdsFileFormat.DDS_FORMAT_R5G6B5:
                {
                    m_flags			= ( int )PixelFormatFlags.DDS_RGB;
                    m_fourCC		= 0;
                    m_rgbBitCount	= 16;
                    m_rBitMask		= 0x0000f800;
                    m_gBitMask		= 0x000007e0;
                    m_bBitMask		= 0x0000001f;
                    m_aBitMask		= 0x00000000;
                    break;
                }
                case DdsFileFormat.DDS_FORMAT_A8L8:
                {
                    m_flags = (int)PixelFormatFlags.DDS_RGB + (int)PixelFormatFlags.DDS_ALPHAPIXELS;
                    m_fourCC = 0;
                    m_rgbBitCount = 16;
                    m_rBitMask = 0x000000ff;
                    m_gBitMask = 0x00000000;
                    m_bBitMask = 0x00000000;
                    m_aBitMask = 0x0000ff00;
                    break;

                }
                default:
                    break;
            }
        }