示例#1
0
        public void ExtractBitmap(Bitmap bitmap, int imageIndex, Stream outStream)
        {
            var resource        = bitmap.Resources[imageIndex];
            var resourceContext = new ResourceSerializationContext(CacheContext, resource.Resource);
            var definition      = ExtractResourceDefinition(resource, resourceContext);

            var header = new DDSHeader(definition.Texture.Definition);

            header.Write(new EndianWriter(outStream));

            ExtractResourceData(definition, resource, outStream);
        }
示例#2
0
        private void ExtractBitmap(CacheFile.IndexItem blamTag, string directory)
        {
            Console.WriteLine($"{blamTag.Name}");
            //
            // Load the Blam tag definition
            //

            var blamContext = new CacheSerializationContext(ref BlamCache, blamTag);

            var bitmap = BlamCache.Deserializer.Deserialize <Bitmap>(blamContext);


            var    ddsOutDir   = directory;
            string bitmap_name = blamTag.Name.Replace('\\', '_');

            if (bitmap.Images.Count > 1)
            {
                ddsOutDir = Path.Combine(directory, bitmap_name);
                Directory.CreateDirectory(ddsOutDir);
            }

            for (var i = 0; i < bitmap.Images.Count; i++)
            {
                var outPath = Path.Combine(ddsOutDir, ((bitmap.Images.Count > 1) ? i.ToString() : bitmap_name) + ".dds");
                var image   = bitmap.Images[i];
                //
                // Get bitmap data and write file
                //

                BaseBitmap baseBitmap = ExtractBitmapData(bitmap, i);

                // Bitmap is not valid (not a failure to convert, tag data is not valid / no data to convert
                if (baseBitmap == null)
                {
                    return;
                }

                var header = new DDSHeader(baseBitmap);


                using (var outStream = File.Open(outPath, FileMode.Create, FileAccess.Write))
                {
                    header.Write(new EndianWriter(outStream));
                    var dataStream = new MemoryStream(baseBitmap.Data);
                    StreamUtil.Copy(dataStream, outStream, baseBitmap.Data.Length);
                }
            }
        }
示例#3
0
        private static void GenerateCompressedMipMaps(BaseBitmap bitmap)
        {
            string tempBitmap = $@"Temp\{Guid.NewGuid().ToString()}.dds";

            if (!Directory.Exists(@"Temp"))
            {
                Directory.CreateDirectory(@"Temp");
            }

            //Write input dds
            bitmap.MipMapCount = 0;
            var header = new DDSHeader(bitmap);


            using (var outStream = File.Open(tempBitmap, FileMode.Create, FileAccess.Write))
            {
                header.Write(new EndianWriter(outStream));
                var dataStream = new MemoryStream(bitmap.Data);
                StreamUtil.Copy(dataStream, outStream, bitmap.Data.Length);
            }

            string args = " ";

            switch (bitmap.Format)
            {
            case BitmapFormat.Dxn:
                args += "-bc5 -resize -normal";
                break;

            case BitmapFormat.Dxt1:
                args += "-bc1 ";
                break;

            case BitmapFormat.Dxt3:
                args += "-bc2 ";
                break;

            case BitmapFormat.Dxt5:
                args += "-bc3 ";
                break;

            default:
                bitmap.MipMapCount = 0;
                if (File.Exists(tempBitmap))
                {
                    File.Delete(tempBitmap);
                }
                return;
            }

            args += $"{tempBitmap} {tempBitmap}";

            ProcessStartInfo info = new ProcessStartInfo(@"Tools\nvcompress.exe")
            {
                Arguments              = args,
                CreateNoWindow         = true,
                WindowStyle            = ProcessWindowStyle.Hidden,
                UseShellExecute        = false,
                RedirectStandardError  = false,
                RedirectStandardOutput = false,
                RedirectStandardInput  = false
            };
            Process nvcompress = Process.Start(info);

            nvcompress.WaitForExit();

            byte[] result;
            using (var ddsStream = File.OpenRead(tempBitmap))
            {
                header.Read(new EndianReader(ddsStream));
                var dataSize = (int)(ddsStream.Length - ddsStream.Position);

                int mipMapCount = header.MipMapCount - 1;

                bitmap.Width  = header.Width;
                bitmap.Height = header.Height;

                // Remove lowest DXN mipmaps to prevent issues with D3D memory allocation.
                if (bitmap.Format == BitmapFormat.Dxn)
                {
                    dataSize = BitmapUtils.RoundSize(bitmap.Width, 4) * BitmapUtils.RoundSize(bitmap.Height, 4);
                    if (mipMapCount > 0)
                    {
                        if (bitmap.Format == BitmapFormat.Dxn)
                        {
                            var width  = bitmap.Width;
                            var height = bitmap.Height;

                            dataSize = BitmapUtils.RoundSize(width, 4) * BitmapUtils.RoundSize(height, 4);

                            mipMapCount = 0;
                            while ((width >= 8) && (height >= 8))
                            {
                                width    /= 2;
                                height   /= 2;
                                dataSize += BitmapUtils.RoundSize(width, 4) * BitmapUtils.RoundSize(height, 4);
                                mipMapCount++;
                            }
                        }
                    }
                }
                bitmap.MipMapCount = mipMapCount;
                byte[] raw = new byte[dataSize];
                ddsStream.Read(raw, 0, dataSize);
                result      = raw;
                bitmap.Data = result;
            }

            if (File.Exists(tempBitmap))
            {
                File.Delete(tempBitmap);
            }
        }
示例#4
0
		public override void EncodeToFile( Stream input, string outFileName, Codec.CodecData data )
		{
			// Unwrap codecDataPtr - data is cleaned by calling function
			var imgData = (ImageData)data;

			// Check size for cube map faces
			var isCubeMap = imgData.size ==
			                Image.CalculateSize( imgData.numMipMaps, 6, imgData.width, imgData.height, imgData.depth,
			                                     imgData.format );

			// Establish texture attributes
			var isVolume = imgData.depth > 1;
			var isFloat32r = imgData.format == PixelFormat.FLOAT32_R;
			var hasAlpha = false;
			var notImplemented = false;
			var notImplementedString = string.Empty;

			// Check for all the 'not implemented' conditions
			if ( imgData.numMipMaps != 0 )
			{
				// No mip map functionality yet
				notImplemented = true;
				notImplementedString += " mipmaps";
			}

			if ( ( isVolume == true ) && ( imgData.width != imgData.height ) )
			{
				// Square textures only
				notImplemented = true;
				notImplementedString += " non square textures";
			}

			var size = 1;
			while ( size < imgData.width )
			{
				size <<= 1;
			}
			if ( size != imgData.width )
			{
				// Power two textures only
				notImplemented = true;
				notImplementedString += " non power two textures";
			}

			switch ( imgData.format )
			{
				case PixelFormat.A8R8G8B8:
				case PixelFormat.X8R8G8B8:
				case PixelFormat.R8G8B8:
				case PixelFormat.FLOAT32_R:
					break;

				default:
					// No crazy FOURCC or 565 et al. file formats at this stage
					notImplemented = true;
					notImplementedString = " unsupported pixel format";
					break;
			}

			// Except if any 'not implemented' conditions were met
			if ( notImplemented )
			{
				throw new NotImplementedException( string.Format( "DDS encoding for{0} not supported", notImplementedString ) );
			}
			else
			{
				// Build header and write to disk

				// Variables for some DDS header flags
				var ddsHeaderFlags = 0;
				var ddsHeaderRgbBits = 0;
				var ddsHeaderSizeOrPitch = 0;
				var ddsHeaderCaps1 = 0;
				var ddsHeaderCaps2 = 0;
				var ddsMagic = this.DDS_MAGIC;

				// Initalise the header flags
				ddsHeaderFlags = ( isVolume )
				                 	? DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_DEPTH | DDSD_PIXELFORMAT
				                 	: DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;

				// Initalise the rgbBits flags
				switch ( imgData.format )
				{
					case PixelFormat.A8R8G8B8:
						ddsHeaderRgbBits = 8*4;
						hasAlpha = true;
						break;

					case PixelFormat.X8R8G8B8:
						ddsHeaderRgbBits = 8*4;
						break;

					case PixelFormat.R8G8B8:
						ddsHeaderRgbBits = 8*3;
						break;

					case PixelFormat.FLOAT32_R:
						ddsHeaderRgbBits = 32;
						break;

					default:
						ddsHeaderRgbBits = 0;
						break;
				}
				;

				// Initalise the SizeOrPitch flags (power two textures for now)
				ddsHeaderSizeOrPitch = ddsHeaderRgbBits*imgData.width;

				// Initalise the caps flags
				ddsHeaderCaps1 = ( isVolume || isCubeMap ) ? DDSCAPS_COMPLEX | DDSCAPS_TEXTURE : DDSCAPS_TEXTURE;
				if ( isVolume )
				{
					ddsHeaderCaps2 = DDSCAPS2_VOLUME;
				}
				else if ( isCubeMap )
				{
					ddsHeaderCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_NEGATIVEX |
					                 DDSCAPS2_CUBEMAP_POSITIVEY | DDSCAPS2_CUBEMAP_NEGATIVEY | DDSCAPS2_CUBEMAP_POSITIVEZ |
					                 DDSCAPS2_CUBEMAP_NEGATIVEZ;
				}

				// Populate the DDS header information
				var ddsHeader = new DDSHeader();
				ddsHeader.size = DDS_HEADER_SIZE;
				ddsHeader.flags = ddsHeaderFlags;
				ddsHeader.width = imgData.width;
				ddsHeader.height = imgData.height;
				ddsHeader.depth = isVolume ? imgData.depth : 0;
				ddsHeader.depth = isCubeMap ? 6 : ddsHeader.depth;
				ddsHeader.mipMapCount = 0;
				ddsHeader.sizeOrPitch = ddsHeaderSizeOrPitch;
				ddsHeader.reserved1 = new int[11];

				ddsHeader.reserved2 = 0;
				ddsHeader.pixelFormat.size = DDS_PIXELFORMAT_SIZE;
				ddsHeader.pixelFormat.flags = ( hasAlpha ) ? DDPF_RGB | DDPF_ALPHAPIXELS : DDPF_RGB;
				ddsHeader.pixelFormat.flags = ( isFloat32r ) ? DDPF_FOURCC : ddsHeader.pixelFormat.flags;
				ddsHeader.pixelFormat.fourCC = ( isFloat32r ) ? D3DFMT_R32F : 0;
				ddsHeader.pixelFormat.rgbBits = ddsHeaderRgbBits;

				ddsHeader.pixelFormat.alphaMask = hasAlpha ? unchecked( (int)0xFF000000 ) : 0x00000000;
				ddsHeader.pixelFormat.alphaMask = isFloat32r ? 0x00000000 : ddsHeader.pixelFormat.alphaMask;
				ddsHeader.pixelFormat.redMask = isFloat32r ? unchecked( (int)0xFFFFFFFF ) : 0x00FF0000;
				ddsHeader.pixelFormat.greenMask = isFloat32r ? 0x00000000 : 0x0000FF00;
				ddsHeader.pixelFormat.blueMask = isFloat32r ? 0x00000000 : 0x000000FF;

				ddsHeader.caps.caps1 = ddsHeaderCaps1;
				ddsHeader.caps.caps2 = ddsHeaderCaps2;
				ddsHeader.caps.reserved[ 0 ] = 0;
				ddsHeader.caps.reserved[ 1 ] = 0;

				// Swap endian
				using ( var wrap = BufferBase.Wrap( ddsMagic, 2 ) )
				{
					_flipEndian( wrap, sizeof ( uint ), 1 );
				}

				using ( var wrap = BufferBase.Wrap( ddsHeader, Memory.SizeOf( typeof( DDSHeader ) ) ) )
				{
					_flipEndian( wrap, 4, Memory.SizeOf( typeof ( DDSHeader ) )/4 );
				}

				// Write the file
				using ( var br = new BinaryWriter( File.Open( outFileName, FileMode.OpenOrCreate, FileAccess.Write ) ) )
				{
					br.Write( ddsMagic );
					ddsHeader.Write( br );
					// XXX flipEndian on each pixel chunk written unless isFloat32r ?
					var inputData = new byte[(int)input.Length];
					input.Read( inputData, 0, inputData.Length );
					br.Write( inputData );
				}
			}
		}
示例#5
0
文件: DDSCodec.cs 项目: axiom3d/axiom
        public override void EncodeToFile(Stream input, string outFileName, Codec.CodecData data)
        {
            // Unwrap codecDataPtr - data is cleaned by calling function
            var imgData = (ImageData)data;

            // Check size for cube map faces
            var isCubeMap = imgData.size ==
                            Image.CalculateSize(imgData.numMipMaps, 6, imgData.width, imgData.height, imgData.depth,
                                                imgData.format);

            // Establish texture attributes
            var isVolume             = imgData.depth > 1;
            var isFloat32r           = imgData.format == PixelFormat.FLOAT32_R;
            var hasAlpha             = false;
            var notImplemented       = false;
            var notImplementedString = string.Empty;

            // Check for all the 'not implemented' conditions
            if (imgData.numMipMaps != 0)
            {
                // No mip map functionality yet
                notImplemented        = true;
                notImplementedString += " mipmaps";
            }

            if ((isVolume == true) && (imgData.width != imgData.height))
            {
                // Square textures only
                notImplemented        = true;
                notImplementedString += " non square textures";
            }

            var size = 1;

            while (size < imgData.width)
            {
                size <<= 1;
            }
            if (size != imgData.width)
            {
                // Power two textures only
                notImplemented        = true;
                notImplementedString += " non power two textures";
            }

            switch (imgData.format)
            {
            case PixelFormat.A8R8G8B8:
            case PixelFormat.X8R8G8B8:
            case PixelFormat.R8G8B8:
            case PixelFormat.FLOAT32_R:
                break;

            default:
                // No crazy FOURCC or 565 et al. file formats at this stage
                notImplemented       = true;
                notImplementedString = " unsupported pixel format";
                break;
            }

            // Except if any 'not implemented' conditions were met
            if (notImplemented)
            {
                throw new NotImplementedException(string.Format("DDS encoding for{0} not supported", notImplementedString));
            }
            else
            {
                // Build header and write to disk

                // Variables for some DDS header flags
                var ddsHeaderFlags       = 0;
                var ddsHeaderRgbBits     = 0;
                var ddsHeaderSizeOrPitch = 0;
                var ddsHeaderCaps1       = 0;
                var ddsHeaderCaps2       = 0;
                var ddsMagic             = this.DDS_MAGIC;

                // Initalise the header flags
                ddsHeaderFlags = (isVolume)
                                     ? DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_DEPTH | DDSD_PIXELFORMAT
                                     : DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;

                // Initalise the rgbBits flags
                switch (imgData.format)
                {
                case PixelFormat.A8R8G8B8:
                    ddsHeaderRgbBits = 8 * 4;
                    hasAlpha         = true;
                    break;

                case PixelFormat.X8R8G8B8:
                    ddsHeaderRgbBits = 8 * 4;
                    break;

                case PixelFormat.R8G8B8:
                    ddsHeaderRgbBits = 8 * 3;
                    break;

                case PixelFormat.FLOAT32_R:
                    ddsHeaderRgbBits = 32;
                    break;

                default:
                    ddsHeaderRgbBits = 0;
                    break;
                }
                ;

                // Initalise the SizeOrPitch flags (power two textures for now)
                ddsHeaderSizeOrPitch = ddsHeaderRgbBits * imgData.width;

                // Initalise the caps flags
                ddsHeaderCaps1 = (isVolume || isCubeMap) ? DDSCAPS_COMPLEX | DDSCAPS_TEXTURE : DDSCAPS_TEXTURE;
                if (isVolume)
                {
                    ddsHeaderCaps2 = DDSCAPS2_VOLUME;
                }
                else if (isCubeMap)
                {
                    ddsHeaderCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_NEGATIVEX |
                                     DDSCAPS2_CUBEMAP_POSITIVEY | DDSCAPS2_CUBEMAP_NEGATIVEY | DDSCAPS2_CUBEMAP_POSITIVEZ |
                                     DDSCAPS2_CUBEMAP_NEGATIVEZ;
                }

                // Populate the DDS header information
                var ddsHeader = new DDSHeader();
                ddsHeader.size        = DDS_HEADER_SIZE;
                ddsHeader.flags       = ddsHeaderFlags;
                ddsHeader.width       = imgData.width;
                ddsHeader.height      = imgData.height;
                ddsHeader.depth       = isVolume ? imgData.depth : 0;
                ddsHeader.depth       = isCubeMap ? 6 : ddsHeader.depth;
                ddsHeader.mipMapCount = 0;
                ddsHeader.sizeOrPitch = ddsHeaderSizeOrPitch;
                ddsHeader.reserved1   = new int[11];

                ddsHeader.reserved2           = 0;
                ddsHeader.pixelFormat.size    = DDS_PIXELFORMAT_SIZE;
                ddsHeader.pixelFormat.flags   = (hasAlpha) ? DDPF_RGB | DDPF_ALPHAPIXELS : DDPF_RGB;
                ddsHeader.pixelFormat.flags   = (isFloat32r) ? DDPF_FOURCC : ddsHeader.pixelFormat.flags;
                ddsHeader.pixelFormat.fourCC  = (isFloat32r) ? D3DFMT_R32F : 0;
                ddsHeader.pixelFormat.rgbBits = ddsHeaderRgbBits;

                ddsHeader.pixelFormat.alphaMask = hasAlpha ? unchecked ((int)0xFF000000) : 0x00000000;
                ddsHeader.pixelFormat.alphaMask = isFloat32r ? 0x00000000 : ddsHeader.pixelFormat.alphaMask;
                ddsHeader.pixelFormat.redMask   = isFloat32r ? unchecked ((int)0xFFFFFFFF) : 0x00FF0000;
                ddsHeader.pixelFormat.greenMask = isFloat32r ? 0x00000000 : 0x0000FF00;
                ddsHeader.pixelFormat.blueMask  = isFloat32r ? 0x00000000 : 0x000000FF;

                ddsHeader.caps.caps1       = ddsHeaderCaps1;
                ddsHeader.caps.caps2       = ddsHeaderCaps2;
                ddsHeader.caps.reserved[0] = 0;
                ddsHeader.caps.reserved[1] = 0;

                // Swap endian
                using (var wrap = BufferBase.Wrap(ddsMagic, 2))
                {
                    _flipEndian(wrap, sizeof(uint), 1);
                }

                using (var wrap = BufferBase.Wrap(ddsHeader, Memory.SizeOf(typeof(DDSHeader))))
                {
                    _flipEndian(wrap, 4, Memory.SizeOf(typeof(DDSHeader)) / 4);
                }

                // Write the file
                using (var br = new BinaryWriter(File.Open(outFileName, FileMode.OpenOrCreate, FileAccess.Write)))
                {
                    br.Write(ddsMagic);
                    ddsHeader.Write(br);
                    // XXX flipEndian on each pixel chunk written unless isFloat32r ?
                    var inputData = new byte[(int)input.Length];
                    input.Read(inputData, 0, inputData.Length);
                    br.Write(inputData);
                }
            }
        }