예제 #1
0
        private static void CompressDxt(GraphicsProfile profile, TextureContent content, bool generateMipmaps)
        {
            var texData = content.Faces[0][0];

            if (profile == GraphicsProfile.Reach)
            {
                if (!IsPowerOfTwo(texData.Width) || !IsPowerOfTwo(texData.Height))
                {
                    throw new PipelineException("DXT Compressed textures width and height must be powers of two in GraphicsProfile.Reach.");
                }
            }

            var _dxtCompressor = new Compressor();
            var inputOptions   = new InputOptions();

            inputOptions.SetAlphaMode(AlphaMode.Transparency);
            inputOptions.SetTextureLayout(TextureType.Texture2D, texData.Width, texData.Height, 1);

            var pixelData = texData.GetPixelData();

            // Small hack here. NVTT wants 8bit data in BGRA. Flip the B and R channels
            // again here.
            GraphicsUtil.BGRAtoRGBA(pixelData);
            var dataHandle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
            var dataPtr    = dataHandle.AddrOfPinnedObject();

            inputOptions.SetMipmapData(dataPtr, texData.Width, texData.Height, 1, 0, 0);
            inputOptions.SetMipmapGeneration(generateMipmaps);

            var containsFracAlpha = ContainsFractionalAlpha(pixelData);
            var outputOptions     = new OutputOptions();

            outputOptions.SetOutputHeader(false);

            var outputFormat = containsFracAlpha ? Format.DXT5 : Format.DXT1;

            var handler = new DxtDataHandler(content, outputFormat);

            outputOptions.SetOutputHandler(handler.BeginImage, handler.WriteData);

            var compressionOptions = new CompressionOptions();

            compressionOptions.SetFormat(outputFormat);
            compressionOptions.SetQuality(Quality.Fastest);

            _dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions);

            dataHandle.Free();
        }
예제 #2
0
        protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion)
        {
            SurfaceFormat sourceFormat;

            if (!sourceBitmap.TryGetFormat(out sourceFormat))
            {
                return(false);
            }

            SurfaceFormat format;

            TryGetFormat(out format);

            // A shortcut for copying the entire bitmap to another bitmap of the same type and format
            if (format == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion)
            {
                SetPixelData(sourceBitmap.GetPixelData());
                return(true);
            }

            // Destination region copy is not yet supported
            if (destinationRegion != new Rectangle(0, 0, Width, Height))
            {
                return(false);
            }

            // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy
            if (!(sourceBitmap is PixelBitmapContent <Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height)
            {
                try
                {
                    BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion);
                    return(true);
                }
                catch (InvalidOperationException)
                {
                    return(false);
                }
            }

            //SquishFlags targetFormat = SquishFlags.ColourClusterFit;
            Format outputFormat = Format.DXT1;

            switch (format)
            {
            case SurfaceFormat.Dxt1:
                outputFormat = Format.DXT1;
                break;

            case SurfaceFormat.Dxt1SRgb:
                outputFormat = Format.DXT1;
                break;

            case SurfaceFormat.Dxt3:
                outputFormat = Format.DXT3;
                break;

            case SurfaceFormat.Dxt3SRgb:
                outputFormat = Format.DXT3;
                break;

            case SurfaceFormat.Dxt5:
                outputFormat = Format.DXT5;
                break;

            case SurfaceFormat.Dxt5SRgb:
                outputFormat = Format.DXT5;
                break;

            default:
                return(false);
            }

            // libsquish requires RGBA8888
            var colorBitmap = new PixelBitmapContent <Color>(sourceBitmap.Width, sourceBitmap.Height);

            BitmapContent.Copy(sourceBitmap, colorBitmap);

            var sourceData = colorBitmap.GetPixelData();

            /*
             * var dataSize = Squish.GetStorageRequirements(colorBitmap.Width, colorBitmap.Height, targetFormat);
             * var data = new byte[dataSize];
             * var metric = new float[] { 1.0f, 1.0f, 1.0f };
             * Squish.CompressImage(sourceData, colorBitmap.Width, colorBitmap.Height, data, targetFormat, metric);
             * SetPixelData(data);
             */

            var dxtCompressor = new Compressor();
            var inputOptions  = new InputOptions();

            if (outputFormat != Format.DXT1)
            {
                inputOptions.SetAlphaMode(AlphaMode.Premultiplied);
            }
            else
            {
                inputOptions.SetAlphaMode(AlphaMode.None);
            }
            inputOptions.SetTextureLayout(TextureType.Texture2D, colorBitmap.Width, colorBitmap.Height, 1);

            // Small hack here. NVTT wants 8bit data in BGRA. Flip the B and R channels
            // again here.
            GraphicsUtil.BGRAtoRGBA(sourceData);
            var dataHandle = GCHandle.Alloc(sourceData, GCHandleType.Pinned);

            try
            {
                var dataPtr = dataHandle.AddrOfPinnedObject();

                inputOptions.SetMipmapData(dataPtr, colorBitmap.Width, colorBitmap.Height, 1, 0, 0);
                inputOptions.SetMipmapGeneration(false);
                inputOptions.SetGamma(1.0f, 1.0f);

                var outputOptions = new OutputOptions();
                outputOptions.SetOutputHeader(false);

                var handler = new DxtDataHandler(this);
                outputOptions.SetOutputHandler(handler.BeginImage, handler.WriteData);

                var compressionOptions = new CompressionOptions();
                compressionOptions.SetFormat(outputFormat);
                compressionOptions.SetQuality(Quality.Normal);

                dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions);
            }
            finally
            {
                dataHandle.Free();
            }
            return(true);
        }
예제 #3
0
        private static void CompressDxt(GraphicsProfile profile, TextureContent content, bool generateMipmaps, bool premultipliedAlpha, bool sharpAlpha)
        {
            var texData = content.Faces[0][0];

            if (profile == GraphicsProfile.Reach)
            {
                if (!IsPowerOfTwo(texData.Width) || !IsPowerOfTwo(texData.Height))
                {
                    throw new PipelineException("DXT Compressed textures width and height must be powers of two in GraphicsProfile.Reach.");
                }
            }

            var pixelData = texData.GetPixelData();

            // Test the alpha channel to figure out if we have alpha.
            var containsAlpha     = false;
            var containsFracAlpha = false;

            for (var x = 3; x < pixelData.Length; x += 4)
            {
                if (pixelData[x] != 0xFF)
                {
                    containsAlpha = true;

                    if (pixelData[x] != 0x0)
                    {
                        containsFracAlpha = true;
                    }
                }
            }

            var _dxtCompressor = new Compressor();
            var inputOptions   = new InputOptions();

            if (containsAlpha)
            {
                inputOptions.SetAlphaMode(premultipliedAlpha ? AlphaMode.Premultiplied : AlphaMode.Transparency);
            }
            else
            {
                inputOptions.SetAlphaMode(AlphaMode.None);
            }
            inputOptions.SetTextureLayout(TextureType.Texture2D, texData.Width, texData.Height, 1);


            // Small hack here. NVTT wants 8bit data in BGRA. Flip the B and R channels
            // again here.
            GraphicsUtil.BGRAtoRGBA(pixelData);
            var dataHandle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
            var dataPtr    = dataHandle.AddrOfPinnedObject();

            inputOptions.SetMipmapData(dataPtr, texData.Width, texData.Height, 1, 0, 0);
            inputOptions.SetMipmapGeneration(generateMipmaps);
            inputOptions.SetGamma(1.0f, 1.0f);

            var outputOptions = new OutputOptions();

            outputOptions.SetOutputHeader(false);

            var outputFormat = Format.DXT1;

            if (containsFracAlpha)
            {
                if (sharpAlpha)
                {
                    outputFormat = Format.DXT3;
                }
                else
                {
                    outputFormat = Format.DXT5;
                }
            }

            var handler = new DxtDataHandler(content, outputFormat);

            outputOptions.SetOutputHandler(handler.BeginImage, handler.WriteData);

            var compressionOptions = new CompressionOptions();

            compressionOptions.SetFormat(outputFormat);
            compressionOptions.SetQuality(Quality.Normal);

            _dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions);

            dataHandle.Free();
        }