Ejemplo n.º 1
0
        /// <summary>
        /// Gets the alpha levels of the image in the provided region.
        /// </summary>
        /// <param name="texture">The texture</param>
        /// <param name="region">The region of the texture to analyze</param>
        /// <param name="tranparencyColor">The color used as transparent color. If null use standard alpha channel.</param>
        /// <param name="logger">The logger used to log information</param>
        /// <returns></returns>
        public unsafe AlphaLevels GetAlphaLevels(TexImage texture, Rectangle region, Color? tranparencyColor, ILogger logger = null)
        {
            // quick escape when it is possible to know the absence of alpha from the file itself
            var alphaDepth = texture.GetAlphaDepth();
            if(!tranparencyColor.HasValue && alphaDepth == 0)
                return AlphaLevels.NoAlpha;

            // check that we support the format
            var format = texture.Format;
            var pixelSize = format.SizeInBytes();
            if (texture.Dimension != TexImage.TextureDimension.Texture2D || !(format.IsRGBAOrder() || format.IsBGRAOrder() || pixelSize != 4))
            {
                var guessedAlphaLevel = alphaDepth > 0 ? AlphaLevels.InterpolatedAlpha : AlphaLevels.NoAlpha;
                logger?.Debug("Impossible to find alpha levels for texture type {0}. Returning default alpha level '{1}'.", format, guessedAlphaLevel);
                return guessedAlphaLevel;
            }

            // truncate the provided region in order to be sure to be in the texture
            region.Width = Math.Min(region.Width, texture.Width - region.Left);
            region.Height = Math.Min(region.Height, texture.Height- region.Top);

            var alphaLevel = AlphaLevels.NoAlpha;
            var stride = texture.RowPitch;
            var startPtr = (byte*)texture.Data + stride * region.Y + pixelSize * region.X;
            var rowPtr = startPtr;

            if (tranparencyColor.HasValue) // specific case when using a transparency color
            {
                var transparencyValue = format.IsRGBAOrder() ? tranparencyColor.Value.ToRgba() : tranparencyColor.Value.ToBgra();
                
                for (int y = 0; y < region.Height; ++y)
                {
                    var ptr = (int*)rowPtr;

                    for (int x = 0; x < region.Width; x++)
                    {
                        if (*ptr == transparencyValue)
                            return AlphaLevels.MaskAlpha;

                        ptr += 1;
                    }
                    rowPtr += stride;
                }
            }
            else // use default alpha channel
            {
                for (int y = 0; y < region.Height; ++y)
                {
                    var ptr = rowPtr+3;

                    for (int x = 0; x < region.Width; x++)
                    {
                        var value = *ptr;
                        if (value == 0)
                        {
                            if (alphaDepth == 1)
                                return AlphaLevels.MaskAlpha;

                            alphaLevel = AlphaLevels.MaskAlpha;
                        }
                        else if (value != 0xff)
                        {
                            return AlphaLevels.InterpolatedAlpha;
                        }

                        ptr += 4;
                    }
                    rowPtr += stride;
                }
            }

            return alphaLevel;
        }
Ejemplo n.º 2
0
        public static ResultStatus ImportTextureImage(TextureTool textureTool, TexImage texImage, ImportParameters parameters, CancellationToken cancellationToken, Logger logger)
        {
            var assetManager = new AssetManager();

            // Apply transformations
            textureTool.Decompress(texImage, parameters.IsSRgb);

            if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
                return ResultStatus.Cancelled;

            var fromSize =  new Size2(texImage.Width, texImage.Height);
            var targetSize = parameters.DesiredSize;

            // Resize the image
            if (parameters.IsSizeInPercentage)
            {
                targetSize = new Size2((int)(fromSize.Width * targetSize.Width / 100.0f), (int)(fromSize.Height * targetSize.Height / 100.0f));
            }

            // Find the target size
            targetSize = FindBestTextureSize(parameters, fromSize, targetSize, logger);

            // Resize the image only if needed
            if (targetSize != fromSize)
            {
                textureTool.Resize(texImage, targetSize.Width, targetSize.Height, Filter.Rescaling.Lanczos3);
            }

            if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
                return ResultStatus.Cancelled;

            // texture size is now determined, we can cache it
            var textureSize = new Int2(texImage.Width, texImage.Height);

            // Apply the color key
            if (parameters.ColorKeyEnabled)
                textureTool.ColorKey(texImage, parameters.ColorKeyColor);

            if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
                return ResultStatus.Cancelled;


            // Pre-multiply alpha
            if (parameters.PremultiplyAlpha)
                textureTool.PreMultiplyAlpha(texImage);

            if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
                return ResultStatus.Cancelled;


            // Generate mipmaps
            if (parameters.GenerateMipmaps)
            {
                var boxFilteringIsSupported = texImage.Format != PixelFormat.B8G8R8A8_UNorm_SRgb || (MathUtil.IsPow2(textureSize.X) && MathUtil.IsPow2(textureSize.Y));
                textureTool.GenerateMipMaps(texImage, boxFilteringIsSupported? Filter.MipMapGeneration.Box: Filter.MipMapGeneration.Linear);
            }
                
            if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
                return ResultStatus.Cancelled;


            // Convert/Compress to output format
            // TODO: Change alphaFormat depending on actual image content (auto-detection)?
            var outputFormat = DetermineOutputFormat(parameters, textureSize, texImage.Format, texImage.GetAlphaDepth());
            textureTool.Compress(texImage, outputFormat, (TextureConverter.Requests.TextureQuality)parameters.TextureQuality);

            if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
                return ResultStatus.Cancelled;

            // Save the texture
            using (var outputImage = textureTool.ConvertToParadoxImage(texImage))
            {
                if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
                    return ResultStatus.Cancelled;

                assetManager.Save(parameters.OutputUrl, outputImage.ToSerializableVersion());

                logger.Info("Compression successful [{3}] to ({0}x{1},{2})", outputImage.Description.Width, outputImage.Description.Height, outputImage.Description.Format, parameters.OutputUrl);
            }

            return ResultStatus.Successful;
        }