Пример #1
0
        public ResizedImageInfo Resize(DpiPath dpi, string inputsFile)
        {
            var destination = GetFileDestination(dpi);

            if (Info.IsVector)
            {
                destination = Path.ChangeExtension(destination, ".png");
            }

            if (IsUpToDate(Info.Filename, destination, inputsFile, Logger))
            {
                return new ResizedImageInfo {
                           Filename = destination, Dpi = dpi
                }
            }
            ;

            if (tools == null)
            {
                tools = SkiaSharpTools.Create(Info.IsVector, Info.Filename, Info.BaseSize, Info.TintColor, Logger);
            }

            tools.Resize(dpi, destination);

            return(new ResizedImageInfo {
                Filename = destination, Dpi = dpi
            });
        }
    }
Пример #2
0
        public ResizedImageInfo Resize(DpiPath dpi, string destination, Func <Stream>?getStream = null)
        {
            var sw = new Stopwatch();

            sw.Start();

            // 1. if an explicit size was given by the type of image, use that
            // 2. if an explicit size was given in the csproj, use that
            // 3. try determine the best size based on the background then foreground
            var(canvasSize, unscaledCanvasSize) = SkiaSharpTools.GetCanvasSize(
                dpi,
                Info.BaseSize,
                backgroundTools ?? foregroundTools);

            using (var tempBitmap = new SKBitmap(canvasSize.Width, canvasSize.Height))
            {
                Draw(tempBitmap, dpi, unscaledCanvasSize);
                Save(tempBitmap, destination, getStream);
            }

            sw.Stop();
            Logger?.Log($"Save app icon took {sw.ElapsedMilliseconds}ms ({destination})");

            return(new ResizedImageInfo {
                Dpi = dpi, Filename = destination
            });
        }
Пример #3
0
        void ProcessBackground(List <ResizedImageInfo> results, DirectoryInfo fullIntermediateOutputPath)
        {
            var backgroundFile         = Info.Filename;
            var backgroundExists       = File.Exists(backgroundFile);
            var backgroundDestFilename = AppIconName + "_background.png";

            if (backgroundExists)
            {
                Logger.Log("Converting Background SVG to PNG: " + backgroundFile);
            }
            else
            {
                Logger.Log("Background was not found (will manufacture): " + backgroundFile);
            }

            foreach (var dpi in DpiPath.Android.AppIconParts)
            {
                var dir         = Path.Combine(fullIntermediateOutputPath.FullName, dpi.Path);
                var destination = Path.Combine(dir, backgroundDestFilename);
                Directory.CreateDirectory(dir);

                Logger.Log($"App Icon Background Part: " + destination);

                if (backgroundExists)
                {
                    // resize the background
                    var tools = SkiaSharpTools.Create(Info.IsVector, Info.Filename, dpi.Size, Info.Color, null, Logger);
                    tools.Resize(dpi, destination, dpiSizeIsAbsolute: true);
                }
                else
                {
                    // manufacture
                    var tools = SkiaSharpTools.CreateImaginary(Info.Color, Logger);
                    tools.Resize(dpi, destination);
                }

                results.Add(new ResizedImageInfo {
                    Dpi = dpi, Filename = destination
                });
            }
        }
Пример #4
0
        public SkiaSharpAppIconTools(ResizeImageInfo info, ILogger logger)
        {
            Info   = info;
            Logger = logger;

            AppIconName = info.OutputName;

            hasForeground = File.Exists(info.ForegroundFilename);

            if (hasForeground)
            {
                foregroundTools = SkiaSharpTools.Create(info.ForegroundIsVector, info.ForegroundFilename, null, info.TintColor, logger);
            }

            backgroundTools = SkiaSharpTools.Create(info.IsVector, info.Filename, null, null, logger);

            backgroundOriginalSize = backgroundTools.GetOriginalSize();

            if (hasForeground)
            {
                foregroundOriginalSize = foregroundTools.GetOriginalSize();
            }
        }
Пример #5
0
        public SkiaSharpAppIconTools(ResizeImageInfo info, ILogger?logger)
        {
            Info   = info;
            Logger = logger;

            AppIconName = info.OutputName;

            var hasBackground = !string.IsNullOrWhiteSpace(info.Filename) && File.Exists(info.Filename);
            var hasForeground = !string.IsNullOrWhiteSpace(info.ForegroundFilename) && File.Exists(info.ForegroundFilename);

            if (!hasBackground && !hasForeground)
            {
                throw new InvalidOperationException("An app icon needs at least one image.");
            }

            if (hasBackground)
            {
                backgroundTools = SkiaSharpTools.Create(info.IsVector, info.Filename, null, null, null, logger);
            }
            if (hasForeground)
            {
                foregroundTools = SkiaSharpTools.Create(info.ForegroundIsVector, info.ForegroundFilename, null, null, info.TintColor, logger);
            }
        }
Пример #6
0
        public static (SKSizeI Scaled, SKSize Unscaled) GetCanvasSize(DpiPath dpi, SKSize?baseSize = null, SkiaSharpTools baseTools = null)
        {
            // if an explicit size was given by the type of image, use that
            if (dpi.Size is SKSize size)
            {
                var scale  = (float)dpi.Scale;
                var scaled = new SKSizeI(
                    (int)(size.Width * scale),
                    (int)(size.Height * scale));
                return(scaled, size);
            }

            // if an explicit size was given in the csproj, use that
            if (baseSize is SKSize bs)
            {
                var scale  = (float)dpi.Scale;
                var scaled = new SKSizeI(
                    (int)(bs.Width * scale),
                    (int)(bs.Height * scale));
                return(scaled, bs);
            }

            // try determine the best size based on the loaded image
            if (baseTools is not null)
            {
                var baseOriginalSize = baseTools.GetOriginalSize();
                var(baseScaledSize, _) = baseTools.GetScaledSize(baseOriginalSize, dpi.Scale);
                return(baseScaledSize, baseOriginalSize);
            }

            throw new InvalidOperationException("The canvas size cannot be calculated if there is no size to start from (DPI size, BaseSize or image size).");
        }
Пример #7
0
        public IEnumerable <ResizedImageInfo> Generate()
        {
            var results = new List <ResizedImageInfo>();

            var fullIntermediateOutputPath = new DirectoryInfo(IntermediateOutputPath);

            var backgroundFile         = Info.Filename;
            var backgroundIsVector     = UseVectors && Info.IsVector;
            var backgroundExt          = backgroundIsVector ? ".xml" : ".png";
            var backgroundDestFilename = AppIconName + "_background" + backgroundExt;

            var foregroundFile         = Info.ForegroundFilename;
            var foregroundExists       = File.Exists(foregroundFile);
            var foregroundIsVector     = !foregroundExists || (UseVectors && Info.ForegroundIsVector);
            var foregroundExt          = foregroundIsVector ? ".xml" : ".png";
            var foregroundDestFilename = AppIconName + "_foreground" + foregroundExt;

            if (backgroundIsVector)
            {
                Logger.Log("Converting Background SVG to Android Drawable Vector: " + backgroundFile);

                var dir         = Path.Combine(fullIntermediateOutputPath.FullName, "drawable-v24");
                var destination = Path.Combine(dir, backgroundDestFilename);
                Directory.CreateDirectory(dir);

                Svg2VectorDrawable.Svg2Vector.Convert(backgroundFile, destination);

                results.Add(new ResizedImageInfo {
                    Dpi = new DpiPath("drawable-v24", 1, "_background"), Filename = destination
                });
            }
            else
            {
                Logger.Log("Converting Background SVG to PNG: " + backgroundFile);

                foreach (var dpi in DpiPath.Android.AppIconParts)
                {
                    var dir         = Path.Combine(fullIntermediateOutputPath.FullName, dpi.Path);
                    var destination = Path.Combine(dir, backgroundDestFilename);
                    Directory.CreateDirectory(dir);

                    Logger.Log($"App Icon Background Part: " + destination);

                    var tools = SkiaSharpTools.Create(Info.IsVector, Info.Filename, dpi.Size, null, Logger);
                    tools.Resize(dpi, destination);

                    results.Add(new ResizedImageInfo {
                        Dpi = dpi, Filename = destination
                    });
                }
            }

            Logger.Log("Looking for Foreground File: " + foregroundFile);

            var foregroundDestinationDir = Path.Combine(fullIntermediateOutputPath.FullName, "drawable");
            var foregroundDestination    = Path.Combine(foregroundDestinationDir, foregroundDestFilename);

            Directory.CreateDirectory(foregroundDestinationDir);

            if (foregroundExists)
            {
                if (foregroundIsVector)
                {
                    Logger.Log("Converting Foreground SVG to Android Drawable Vector: " + foregroundFile);
                    Svg2VectorDrawable.Svg2Vector.Convert(foregroundFile, foregroundDestination);

                    results.Add(new ResizedImageInfo {
                        Dpi = new DpiPath("drawable", 1, "_foreground"), Filename = foregroundDestination
                    });
                }
                else
                {
                    Logger.Log("Converting Foreground SVG to PNG: " + foregroundFile);

                    foreach (var dpi in DpiPath.Android.AppIconParts)
                    {
                        var dir         = Path.Combine(fullIntermediateOutputPath.FullName, dpi.Path);
                        var destination = Path.Combine(dir, foregroundDestFilename);
                        Directory.CreateDirectory(dir);

                        Logger.Log($"App Icon Foreground Part: " + destination);

                        var tools = SkiaSharpTools.Create(Info.ForegroundIsVector, Info.ForegroundFilename, dpi.Size, null, Logger);
                        tools.Resize(dpi, destination);

                        results.Add(new ResizedImageInfo {
                            Dpi = dpi, Filename = destination
                        });
                    }
                }
            }
            else
            {
                Logger.Log("Foreground was not found: " + foregroundFile);

                File.WriteAllText(foregroundDestination, EmptyVectorDrawable);
            }

            // process adaptive icon xml
            {
                var adaptiveIconXmlStr = AdaptiveIconDrawableXml
                                         .Replace("{name}", AppIconName)
                                         .Replace("{backgroundType}", backgroundIsVector ? "drawable" : "mipmap")
                                         .Replace("{foregroundType}", foregroundIsVector ? "drawable" : "mipmap");

                var dir = Path.Combine(fullIntermediateOutputPath.FullName, "mipmap-anydpi-v26");
                var adaptiveIconDestination      = Path.Combine(dir, AppIconName + ".xml");
                var adaptiveIconRoundDestination = Path.Combine(dir, AppIconName + "_round.xml");
                Directory.CreateDirectory(dir);

                // Write out the adaptive icon xml drawables
                File.WriteAllText(adaptiveIconDestination, adaptiveIconXmlStr);
                File.WriteAllText(adaptiveIconRoundDestination, adaptiveIconXmlStr);

                results.Add(new ResizedImageInfo {
                    Dpi = new DpiPath("mipmap-anydpi-v26", 1), Filename = adaptiveIconDestination
                });
                results.Add(new ResizedImageInfo {
                    Dpi = new DpiPath("mipmap-anydpi-v26", 1, "_round"), Filename = adaptiveIconRoundDestination
                });
            }

            return(results);
        }