Example #1
0
        protected override void InitWidgetFromToken(SaveConfigToken token)
        {
            if (token is DdsSaveConfigToken)
            {
                DdsSaveConfigToken ddsToken = (DdsSaveConfigToken)token;
                this.fileFormatList.SelectedIndex = ( int )ddsToken.m_fileFormat;

                this.clusterFit.Checked   = (ddsToken.m_compressorType == 0);
                this.rangeFit.Checked     = (ddsToken.m_compressorType == 1);
                this.iterativeFit.Checked = (ddsToken.m_compressorType == 2);

                this.perceptualMetric.Checked = (ddsToken.m_errorMetric == 0);
                this.uniformMetric.Checked    = !this.perceptualMetric.Checked;

                this.weightColourByAlpha.Checked = ddsToken.m_weightColourByAlpha;

                this.generateMipMaps.Checked = ddsToken.m_generateMipMaps;
            }
            else
            {
                this.fileFormatList.SelectedIndex = 0;

                this.clusterFit.Checked   = true;
                this.rangeFit.Checked     = false;
                this.iterativeFit.Checked = false;

                this.perceptualMetric.Checked = true;
                this.uniformMetric.Checked    = false;

                this.weightColourByAlpha.Checked = false;

                this.generateMipMaps.Checked = false;
            }
        }
 protected DdsSaveConfigToken(DdsSaveConfigToken copyMe)
 {
     m_fileFormat          = copyMe.m_fileFormat;
     m_compressorType      = copyMe.m_compressorType;
     m_errorMetric         = copyMe.m_errorMetric;
     m_weightColourByAlpha = copyMe.m_weightColourByAlpha;
     m_generateMipMaps     = copyMe.m_generateMipMaps;
 }
Example #3
0
        protected override unsafe void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback)
        {
            DdsSaveConfigToken ddsToken = ( DdsSaveConfigToken )token;

            // We need to be able to feast on the goo inside..
            scratchSurface.Clear(ColorBgra.Transparent);

            using (RenderArgs ra = new RenderArgs(scratchSurface))
            {
                input.Render(ra, true);
            }

            // Create the DDS file, and save it..
            DdsFile ddsFile = new DdsFile();

            ddsFile.Save(output, scratchSurface, ddsToken, callback);
        }
Example #4
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;
            }
        }
Example #5
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;
			}
		}
Example #6
0
		protected DdsSaveConfigToken( DdsSaveConfigToken copyMe )
		{
			m_fileFormat			=	copyMe.m_fileFormat;
			m_compressorType		=	copyMe.m_compressorType;
			m_errorMetric			=	copyMe.m_errorMetric;
			m_weightColourByAlpha	=	copyMe.m_weightColourByAlpha;
			m_generateMipMaps		=	copyMe.m_generateMipMaps;
		}