Exemple #1
0
        public void Resize(DpiPath dpi, string destination)
        {
            var originalSize = GetOriginalSize();

            var(scaledSize, scale) = GetScaledSize(originalSize, dpi.Scale);

            var sw = new Stopwatch();

            sw.Start();

            // Allocate
            using (var tempBitmap = new SKBitmap(scaledSize.Width, scaledSize.Height))
            {
                // Draw (copy)
                using (var canvas = new SKCanvas(tempBitmap))
                {
                    canvas.Clear(SKColors.Transparent);
                    canvas.Save();
                    canvas.Scale(scale, scale);
                    DrawUnscaled(canvas);
                }

                // Save (encode)
                using (var pixmap = tempBitmap.PeekPixels())
                    using (var wrapper = new SKFileWStream(destination))
                    {
                        pixmap.Encode(wrapper, SKPngEncoderOptions.Default);
                    }
            }

            sw.Stop();
            Logger?.Log($"Save Image took {sw.ElapsedMilliseconds}ms ({destination})");
        }
Exemple #2
0
        public void Resize(DpiPath dpi, string destination)
        {
            var originalSize = GetOriginalSize();

            var(scaledSize, scale) = GetScaledSize(originalSize, dpi.Scale);

            var sw = new Stopwatch();

            sw.Start();

            // Allocate
            using (var tempBitmap = new SKBitmap(scaledSize.Width, scaledSize.Height))
            {
                // Draw (copy)
                using (var canvas = new SKCanvas(tempBitmap))
                {
                    canvas.Clear(SKColors.Transparent);
                    canvas.Save();
                    canvas.Scale(scale, scale);
                    DrawUnscaled(canvas, scale);
                }

                // Save (encode)
                using var stream = File.Create(destination);
                tempBitmap.Encode(stream, SKEncodedImageFormat.Png, 100);
            }

            sw.Stop();
            Logger?.Log($"Save Image took {sw.ElapsedMilliseconds}ms ({destination})");
        }
Exemple #3
0
        public void Resize(DpiPath dpi, string destination)
        {
            int sourceNominalWidth  = Info.BaseSize?.Width ?? (int)svg.Picture.CullRect.Width;
            int sourceNominalHeight = Info.BaseSize?.Height ?? (int)svg.Picture.CullRect.Height;
            var resizeRatio         = dpi.Scale;

            // Find the actual size of the SVG
            var sourceActualWidth  = svg.Picture.CullRect.Width;
            var sourceActualHeight = svg.Picture.CullRect.Height;

            // Figure out what the ratio to convert the actual image size to the nominal size is
            var nominalRatio = Math.Max((double)sourceNominalWidth / (double)sourceActualWidth, (double)sourceNominalHeight / (double)sourceActualHeight);

            // Multiply nominal ratio by the resize ratio to get our final ratio we actually adjust by
            var adjustRatio = nominalRatio * (double)resizeRatio;

            // Figure out our scaled width and height to make a new canvas for
            //var scaledWidth = sourceActualWidth * adjustRatio;
            //var scaledHeight = sourceActualHeight * adjustRatio;

            var sw = new Stopwatch();

            sw.Start();

            using (var stream = File.OpenWrite(destination))
            {
                svg.Picture.ToImage(stream, SKColors.Empty, SKEncodedImageFormat.Png, 100, (float)adjustRatio, (float)adjustRatio, SKColorType.Argb4444, SKAlphaType.Premul);
            }

            sw.Stop();
            Logger?.Log($"Save Image took {sw.ElapsedMilliseconds}ms");
        }
Exemple #4
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
            });
        }
    }
        void ProcessAppIcon(SharedImageInfo img, ConcurrentBag <ResizedImageInfo> resizedImages)
        {
            var appIconName = img.OutputName;

            // Generate the actual bitmap app icons themselves
            var appIconDpis = DpiPath.GetAppIconDpis(PlatformType, appIconName);

            Log.LogMessage(MessageImportance.Low, $"App Icon");

            // Apple and Android have special additional files to generate for app icons
            if (PlatformType == "android")
            {
                Log.LogMessage(MessageImportance.Low, $"Android Adaptive Icon Generator");

                appIconName = appIconName.ToLowerInvariant();

                var adaptiveIconGen = new AndroidAdaptiveIconGenerator(img, appIconName, IntermediateOutputPath, this);
                var iconsGenerated  = adaptiveIconGen.Generate();

                foreach (var iconGenerated in iconsGenerated)
                {
                    resizedImages.Add(iconGenerated);
                }
            }
            else if (PlatformType == "ios")
            {
                Log.LogMessage(MessageImportance.Low, $"iOS Icon Assets Generator");

                var appleAssetGen = new AppleIconAssetsGenerator(img, appIconName, IntermediateOutputPath, appIconDpis, this);

                var assetsGenerated = appleAssetGen.Generate();

                foreach (var assetGenerated in assetsGenerated)
                {
                    resizedImages.Add(assetGenerated);
                }
            }

            Log.LogMessage(MessageImportance.Low, $"Generating App Icon Bitmaps for DPIs");

            var appTool = new SkiaSharpAppIconTools(img, this);

            Log.LogMessage(MessageImportance.Low, $"App Icon: Intermediate Path " + IntermediateOutputPath);

            foreach (var dpi in appIconDpis)
            {
                Log.LogMessage(MessageImportance.Low, $"App Icon: " + dpi);

                var destination = Resizer.GetFileDestination(img, dpi, IntermediateOutputPath)
                                  .Replace("{name}", appIconName);

                Log.LogMessage(MessageImportance.Low, $"App Icon Destination: " + destination);

                appTool.Resize(dpi, Path.ChangeExtension(destination, ".png"));
            }
        }
Exemple #6
0
 public (SKSizeI, float) GetScaledSize(SKSize originalSize, DpiPath dpi)
 {
     if (dpi.Size.HasValue)
     {
         return(GetScaledSize(originalSize, dpi.Scale, dpi.Size.Value));
     }
     else
     {
         return(GetScaledSize(originalSize, dpi.Scale));
     }
 }
        void ProcessImageCopy(SharedImageInfo img, DpiPath originalScaleDpi, ConcurrentBag <ResizedImageInfo> resizedImages)
        {
            var resizer = new Resizer(img, IntermediateOutputPath, this);

            Log.LogMessage(MessageImportance.Low, $"Copying {img.Filename}");

            var r = resizer.CopyFile(originalScaleDpi, InputsFile, PlatformType.ToLower().Equals("android"));

            resizedImages.Add(r);

            Log.LogMessage(MessageImportance.Low, $"Copied {img.Filename}");
        }
Exemple #8
0
        public static string GetFileDestination(SharedImageInfo info, DpiPath dpi, string intermediateOutputPath)
        {
            var fullIntermediateOutputPath = new DirectoryInfo(intermediateOutputPath);

            var destination = Path.Combine(fullIntermediateOutputPath.FullName, dpi.Path, info.OutputName + dpi.FileSuffix + info.OutputExtension);

            var fileInfo = new FileInfo(destination);

            if (!fileInfo.Directory.Exists)
            {
                fileInfo.Directory.Create();
            }

            return(destination);
        }
Exemple #9
0
        public ResizedImageInfo CopyFile(DpiPath dpi, string inputsFile, bool isAndroid = false)
        {
            var destination   = GetFileDestination(dpi);
            var androidVector = false;

            if (isAndroid && Info.IsVector && !Info.Resize)
            {
                // Update destination to be .xml file
                destination   = Path.ChangeExtension(destination, ".xml");
                androidVector = true;
            }

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

            if (androidVector)
            {
                Logger.Log("Converting SVG to Android Drawable Vector: " + Info.Filename);

                // Transform into an android vector drawable
                var convertErr = Svg2VectorDrawable.Svg2Vector.Convert(Info.Filename, destination);
                if (!string.IsNullOrEmpty(convertErr))
                {
                    throw new Svg2AndroidDrawableConversionException(convertErr, Info.Filename);
                }
            }
            else
            {
                // Otherwise just copy it straight
                File.Copy(Info.Filename, destination, true);
            }

            return(new ResizedImageInfo {
                Filename = destination, Dpi = dpi
            });
        }
Exemple #10
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 (Info.IsVector)
            {
                if (svgTools == null)
                {
                    svgTools = new SkiaSharpSvgTools(Info, Logger);
                }

                svgTools.Resize(dpi, destination);
            }
            else
            {
                if (bmpTools == null)
                {
                    bmpTools = new SkiaSharpBitmapTools(Info, Logger);
                }

                bmpTools.Resize(dpi, destination);
            }

            return(new ResizedImageInfo {
                Filename = destination, Dpi = dpi
            });
        }
    }
        public void Resize(DpiPath dpi, string destination)
        {
            int sourceNominalWidth  = Info.BaseSize?.Width ?? bmp.Width;
            int sourceNominalHeight = Info.BaseSize?.Height ?? bmp.Height;
            var resizeRatio         = dpi.Scale;

            var sourceActualWidth  = bmp.Width;
            var sourceActualHeight = bmp.Height;

            var nominalRatio = Math.Max((double)sourceNominalWidth / (double)sourceActualWidth, (double)sourceNominalHeight / (double)sourceActualHeight);

            var adjustRatio = nominalRatio * Convert.ToDouble(resizeRatio);

            var newWidth  = (int)Math.Floor(bmp.Width * adjustRatio);
            var newHeight = (int)Math.Floor(bmp.Height * adjustRatio);

            using (var rzBitmap = bmp.Resize(new SKImageInfo(newWidth, newHeight), SKFilterQuality.High))
                using (var img = SKImage.FromBitmap(rzBitmap))
                    using (var data = img.Encode(SKEncodedImageFormat.Png, 100))
                        using (var fs = File.Open(destination, FileMode.Create))
                        {
                            data.SaveTo(fs);
                        }
        }
Exemple #12
0
        public static ResizedImageInfo CopyFile(SharedImageInfo info, DpiPath dpi, string intermediateOutputPath, string inputsFile, ILogger logger, bool isAndroid = false)
        {
            var destination   = Resizer.GetFileDestination(info, dpi, intermediateOutputPath);
            var androidVector = false;

            if (isAndroid && info.IsVector && !info.Resize)
            {
                // TODO: Turn SVG into Vector Drawable format
                // Update destination to be .xml file
                destination   = Path.ChangeExtension(info.Filename, ".xml");
                androidVector = true;
            }

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

            if (androidVector)
            {
                // TODO: Don't just copy, let's transform to android vector
                File.Copy(info.Filename, destination, true);
            }
            else
            {
                // Otherwise just copy it straight
                File.Copy(info.Filename, destination, true);
            }

            return(new ResizedImageInfo {
                Filename = destination, Dpi = dpi
            });
        }
Exemple #13
0
        System.Threading.Tasks.Task DoExecute()
        {
            Svg.SvgDocument.SkipGdiPlusCapabilityCheck = true;

            var images = ParseImageTaskItems(SharedImages);

            var dpis = DpiPath.GetDpis(PlatformType);

            if (dpis == null || dpis.Length <= 0)
            {
                return(System.Threading.Tasks.Task.CompletedTask);
            }

            var originalScaleDpi = DpiPath.GetOriginal(PlatformType);

            var resizedImages = new ConcurrentBag <ResizedImageInfo>();

            System.Threading.Tasks.Parallel.ForEach(images, img =>
            {
                var opStopwatch = new Stopwatch();
                opStopwatch.Start();

                var op = "Resize";

                // By default we resize, but let's make sure
                if (img.Resize)
                {
                    var resizer = new Resizer(img, IntermediateOutputPath, this);

                    foreach (var dpi in dpis)
                    {
                        var r = resizer.Resize(dpi, InputsFile);
                        resizedImages.Add(r);
                    }
                }
                else
                {
                    op = "Copy";
                    // Otherwise just copy the thing over to the 1.0 scale
                    var r = Resizer.CopyFile(img, originalScaleDpi, IntermediateOutputPath, InputsFile, this, PlatformType.ToLower().Equals("android"));
                    resizedImages.Add(r);
                }

                opStopwatch.Stop();

                Log.LogMessage(MessageImportance.Low, $"{op} took {opStopwatch.ElapsedMilliseconds}ms");
            });

            var copiedResources = new List <TaskItem>();

            foreach (var img in resizedImages)
            {
                var    attr     = new Dictionary <string, string>();
                string itemSpec = Path.GetFullPath(img.Filename);

                // Fix the item spec to be relative for mac
                if (bool.TryParse(IsMacEnabled, out bool isMac) && isMac)
                {
                    itemSpec = img.Filename;
                }

                // Add DPI info to the itemspec so we can use it in the targets
                attr.Add("_ResizetizerDpiPath", img.Dpi.Path);
                attr.Add("_ResizetizerDpiScale", img.Dpi.Scale.ToString());

                copiedResources.Add(new TaskItem(itemSpec, attr));
            }

            CopiedResources = copiedResources.ToArray();

            return(System.Threading.Tasks.Task.CompletedTask);
        }
Exemple #14
0
 public string GetFileDestination(DpiPath dpi)
 => GetFileDestination(Info, dpi, IntermediateOutputPath);
        public ResizedImageInfo Resize(DpiPath dpi, string destination)
        {
            var sw = new Stopwatch();

            sw.Start();

            var(bgScaledSize, bgScale) = backgroundTools.GetScaledSize(backgroundOriginalSize, dpi);

            // Allocate
            using (var tempBitmap = new SKBitmap(bgScaledSize.Width, bgScaledSize.Height))
            {
                // Draw (copy)
                using (var canvas = new SKCanvas(tempBitmap))
                {
                    canvas.Clear(SKColors.Transparent);
                    canvas.Save();
                    canvas.Scale(bgScale, bgScale);

                    backgroundTools.DrawUnscaled(canvas);
                    canvas.Restore();

                    if (hasForeground)
                    {
                        var userFgScale = (float)Info.ForegroundScale;

                        // get the ratio to make the foreground fill the background
                        var fitRatio = bgScaledSize.Width / foregroundOriginalSize.Width;

                        // calculate the scale for the foreground to fit the background exactly
                        var(fgScaledSize, fgScale) = foregroundTools.GetScaledSize(foregroundOriginalSize, (decimal)fitRatio);

                        Logger.Log("dpi.Size: " + dpi.Size);
                        Logger.Log("dpi.Scale: " + dpi.Scale);
                        Logger.Log("bgScaledSize: " + bgScaledSize);
                        Logger.Log("bgScale: " + bgScale);
                        Logger.Log("foregroundOriginalSize: " + foregroundOriginalSize);
                        Logger.Log("fgScaledSize: " + fgScaledSize);
                        Logger.Log("fgScale: " + fgScale);
                        Logger.Log("userFgScale: " + userFgScale);

                        // now work out the center as if the canvas was exactly the same size as the foreground
                        var fgScaledSizeCenterX = foregroundOriginalSize.Width / 2;
                        var fgScaledSizeCenterY = foregroundOriginalSize.Height / 2;

                        Logger.Log("fgScaledSizeCenterX: " + fgScaledSizeCenterX);
                        Logger.Log("fgScaledSizeCenterY: " + fgScaledSizeCenterY);

                        // scale so the forground is the same size as the background
                        canvas.Scale(fgScale, fgScale);

                        // scale to the user scale, centering
                        canvas.Scale(userFgScale, userFgScale, fgScaledSizeCenterX, fgScaledSizeCenterY);

                        foregroundTools.DrawUnscaled(canvas);
                    }
                }

                // Save (encode)
                using (var pixmap = tempBitmap.PeekPixels())
                    using (var wrapper = new SKFileWStream(destination))
                    {
                        pixmap.Encode(wrapper, SKPngEncoderOptions.Default);
                    }
            }

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

            return(new ResizedImageInfo {
                Dpi = dpi, Filename = destination
            });
        }
        System.Threading.Tasks.Task DoExecute()
        {
            Svg.SvgDocument.SkipGdiPlusCapabilityCheck = true;

            var images = ParseImageTaskItems(SharedImages);

            var dpis = DpiPath.GetDpis(PlatformType);

            if (dpis == null || dpis.Length <= 0)
            {
                return(System.Threading.Tasks.Task.CompletedTask);
            }

            var originalScaleDpi = DpiPath.GetOriginal(PlatformType);

            var resizedImages = new ConcurrentBag <ResizedImageInfo>();

            System.Threading.Tasks.Parallel.ForEach(images, img =>
            {
                if (img.IsAppIcon)
                {
                    var appIconName = "appicon";                     // Path.GetFileNameWithoutExtension(img.Filename);

                    // Generate the actual bitmap app icons themselves
                    var appIconDpis = DpiPath.GetAppIconDpis(PlatformType, appIconName);

                    Log.LogMessage(MessageImportance.Low, $"App Icon");

                    // Apple and Android have special additional files to generate for app icons
                    if (PlatformType == "android")
                    {
                        Log.LogMessage(MessageImportance.Low, $"Android Adaptive Icon Generator");

                        appIconName = appIconName.ToLowerInvariant();

                        var adaptiveIconGen = new AndroidAdaptiveIconGenerator(img, appIconName, IntermediateOutputPath, this);
                        var iconsGenerated  = adaptiveIconGen.Generate();

                        foreach (var iconGenerated in iconsGenerated)
                        {
                            resizedImages.Add(iconGenerated);
                        }
                    }
                    else if (PlatformType == "ios")
                    {
                        Log.LogMessage(MessageImportance.Low, $"iOS Icon Assets Generator");

                        var appleAssetGen = new AppleIconAssetsGenerator(img, appIconName, IntermediateOutputPath, appIconDpis, this);

                        var assetsGenerated = appleAssetGen.Generate();

                        foreach (var assetGenerated in assetsGenerated)
                        {
                            resizedImages.Add(assetGenerated);
                        }
                    }

                    Log.LogMessage(MessageImportance.Low, $"Generating App Icon Bitmaps for DPIs");

                    var appTool = new SkiaSharpAppIconTools(img, this);

                    Log.LogMessage(MessageImportance.Low, $"App Icon: Intermediate Path " + IntermediateOutputPath);

                    foreach (var dpi in appIconDpis)
                    {
                        Log.LogMessage(MessageImportance.Low, $"App Icon: " + dpi);

                        var destination = Resizer.GetFileDestination(img, dpi, IntermediateOutputPath)
                                          .Replace("{name}", appIconName);
                        Log.LogMessage(MessageImportance.Low, $"App Icon Destination: " + destination);
                        appTool.Resize(dpi, Path.ChangeExtension(destination, ".png"));
                    }
                }
                else
                {
                    var opStopwatch = new Stopwatch();
                    opStopwatch.Start();

                    var op = "Resize";

                    // By default we resize, but let's make sure
                    if (img.Resize)
                    {
                        var resizer = new Resizer(img, IntermediateOutputPath, this);

                        foreach (var dpi in dpis)
                        {
                            Log.LogMessage(MessageImportance.Low, $"Resizing {img.Filename}");

                            var r = resizer.Resize(dpi, InputsFile);
                            resizedImages.Add(r);

                            Log.LogMessage(MessageImportance.Low, $"Resized {img.Filename}");
                        }
                    }
                    else
                    {
                        op = "Copy";

                        Log.LogMessage(MessageImportance.Low, $"Copying {img.Filename}");
                        // Otherwise just copy the thing over to the 1.0 scale
                        var r = Resizer.CopyFile(img, originalScaleDpi, IntermediateOutputPath, InputsFile, this, PlatformType.ToLower().Equals("android"));
                        resizedImages.Add(r);
                        Log.LogMessage(MessageImportance.Low, $"Copied {img.Filename}");
                    }

                    opStopwatch.Stop();

                    Log.LogMessage(MessageImportance.Low, $"{op} took {opStopwatch.ElapsedMilliseconds}ms");
                }
            });

            var copiedResources = new List <TaskItem>();

            foreach (var img in resizedImages)
            {
                var    attr     = new Dictionary <string, string>();
                string itemSpec = Path.GetFullPath(img.Filename);

                // Fix the item spec to be relative for mac
                if (bool.TryParse(IsMacEnabled, out bool isMac) && isMac)
                {
                    itemSpec = img.Filename;
                }

                // Add DPI info to the itemspec so we can use it in the targets
                attr.Add("_ResizetizerDpiPath", img.Dpi.Path);
                attr.Add("_ResizetizerDpiScale", img.Dpi.Scale.ToString());

                copiedResources.Add(new TaskItem(itemSpec, attr));
            }

            CopiedResources = copiedResources.ToArray();

            return(System.Threading.Tasks.Task.CompletedTask);
        }
        System.Threading.Tasks.Task DoExecute()
        {
            Svg.SvgDocument.SkipGdiPlusCapabilityCheck = true;

            var images = ParseImageTaskItems(SharedImages);

            var dpis = DpiPath.GetDpis(PlatformType);

            if (dpis == null || dpis.Length <= 0)
            {
                return(System.Threading.Tasks.Task.CompletedTask);
            }

            var originalScaleDpi = DpiPath.GetOriginal(PlatformType);

            var resizedImages = new ConcurrentBag <ResizedImageInfo>();

            System.Threading.Tasks.Parallel.ForEach(images, img =>
            {
                try
                {
                    var opStopwatch = new Stopwatch();
                    opStopwatch.Start();

                    string op;

                    if (img.IsAppIcon)
                    {
                        // App icons are special
                        ProcessAppIcon(img, resizedImages);

                        op = "App Icon";
                    }
                    else
                    {
                        // By default we resize, but let's make sure
                        if (img.Resize)
                        {
                            ProcessImageResize(img, dpis, resizedImages);

                            op = "Resize";
                        }
                        else
                        {
                            // Otherwise just copy the thing over to the 1.0 scale
                            ProcessImageCopy(img, originalScaleDpi, resizedImages);

                            op = "Copy";
                        }
                    }

                    opStopwatch.Stop();

                    Log.LogMessage(MessageImportance.Low, $"{op} took {opStopwatch.ElapsedMilliseconds}ms");
                }
                catch (Exception ex)
                {
                    Log.LogErrorFromException(ex);

                    throw;
                }
            });

            var copiedResources = new List <TaskItem>();

            foreach (var img in resizedImages)
            {
                var    attr     = new Dictionary <string, string>();
                string itemSpec = Path.GetFullPath(img.Filename);

                // Fix the item spec to be relative for mac
                if (bool.TryParse(IsMacEnabled, out bool isMac) && isMac)
                {
                    itemSpec = img.Filename;
                }

                // Add DPI info to the itemspec so we can use it in the targets
                attr.Add("_ResizetizerDpiPath", img.Dpi.Path);
                attr.Add("_ResizetizerDpiScale", img.Dpi.Scale.ToString());

                copiedResources.Add(new TaskItem(itemSpec, attr));
            }

            CopiedResources = copiedResources.ToArray();

            return(System.Threading.Tasks.Task.CompletedTask);
        }