From 8a20af9ab6c17a392cc5abcc54eccec160e70f89 Mon Sep 17 00:00:00 2001 From: Emiliano Magliocca Date: Sat, 2 May 2020 09:05:58 +0300 Subject: [PATCH 1/7] Update ImageSharp --- Yugen.Mosaic.Uwp/Package.appxmanifest | 2 +- .../Processors/AdjustHueProcessor.cs | 12 +++++----- .../Processors/ApplyTileFoundProcessor.cs | 14 +++++------ .../Processors/GetTileAverageProcessor.cs | 12 +++++----- .../Processors/GetTilesAverageProcessor.cs | 13 +++++----- .../Processors/PlainColorProcessor.cs | 24 +++++++++---------- Yugen.Mosaic.Uwp/Services/MosaicService.cs | 1 + Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs | 1 + Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj | 14 +++++------ 9 files changed, 46 insertions(+), 47 deletions(-) diff --git a/Yugen.Mosaic.Uwp/Package.appxmanifest b/Yugen.Mosaic.Uwp/Package.appxmanifest index f925bd5..06d7faa 100644 --- a/Yugen.Mosaic.Uwp/Package.appxmanifest +++ b/Yugen.Mosaic.Uwp/Package.appxmanifest @@ -7,7 +7,7 @@ IgnorableNamespaces="uap mp"> diff --git a/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs b/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs index 9a03a40..e39ebac 100644 --- a/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs @@ -1,10 +1,10 @@ using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; using System; using System.Threading.Tasks; +using Rectangle = SixLabors.ImageSharp.Rectangle; namespace Yugen.Mosaic.Uwp.Processors { @@ -20,13 +20,13 @@ public AdjustHueProcessor(Image inputImage, Rgba32 averageColor) } /// - public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) where TPixel : struct, IPixel + public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel { - return new AdjustHueProcessor(this, source, sourceRectangle); + return new AdjustHueProcessor(configuration, this, source, sourceRectangle); } } - public class AdjustHueProcessor : IImageProcessor where TPixel : struct, IPixel + public class AdjustHueProcessor : IImageProcessor where TPixel : unmanaged, IPixel { /// /// The source instance to modify @@ -41,7 +41,7 @@ public class AdjustHueProcessor : IImageProcessor where TPixel : /// The defining the processor parameters /// The source for the current processor instance /// The source area to process for the current processor instance - public AdjustHueProcessor(AdjustHueProcessor definition, Image source, Rectangle sourceRectangle) + public AdjustHueProcessor(Configuration configuration, AdjustHueProcessor definition, Image source, Rectangle sourceRectangle) { _source = source; _inputImage = definition.InputImage; @@ -49,7 +49,7 @@ public AdjustHueProcessor(AdjustHueProcessor definition, Image source, R } /// - public void Apply() + public void Execute() { //int width = Source.Width; //Image source = Source; diff --git a/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs b/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs index 1fb9632..44b8b31 100644 --- a/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs @@ -1,11 +1,9 @@ using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; -using System; using System.Threading.Tasks; +using Rectangle = SixLabors.ImageSharp.Rectangle; namespace Yugen.Mosaic.Uwp.Processors { @@ -29,13 +27,13 @@ public ApplyTileFoundProcessor(int x, int y, int width, int height, Image - public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) where TPixel : struct, IPixel + public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel { - return new ApplyTileFoundProcessor(this, source, sourceRectangle); + return new ApplyTileFoundProcessor(configuration, this, source, sourceRectangle); } } - public class ApplyTileFoundProcessor : IImageProcessor where TPixel : struct, IPixel + public class ApplyTileFoundProcessor : IImageProcessor where TPixel : unmanaged, IPixel { /// /// The source instance to modify @@ -55,7 +53,7 @@ public class ApplyTileFoundProcessor : IImageProcessor where TPi /// The defining the processor parameters /// The source for the current processor instance /// The source area to process for the current processor instance - public ApplyTileFoundProcessor(ApplyTileFoundProcessor definition, Image source, Rectangle sourceRectangle) + public ApplyTileFoundProcessor(Configuration configuration, ApplyTileFoundProcessor definition, Image source, Rectangle sourceRectangle) { _source = source; @@ -68,7 +66,7 @@ public ApplyTileFoundProcessor(ApplyTileFoundProcessor definition, Image } /// - public void Apply() + public void Execute() { Parallel.For(0, _height, h => { diff --git a/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs b/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs index 6abb968..da544b2 100644 --- a/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs @@ -1,11 +1,11 @@ using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; using System; using System.Threading.Tasks; +using Rectangle = SixLabors.ImageSharp.Rectangle; namespace Yugen.Mosaic.Uwp.Processors { @@ -29,13 +29,13 @@ public GetTileAverageProcessor(int x, int y, int width, int height, Image - public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) where TPixel : struct, IPixel + public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel { - return new GetTileAverageProcessor(this, source, sourceRectangle); + return new GetTileAverageProcessor(configuration, this, source, sourceRectangle); } } - public class GetTileAverageProcessor : IImageProcessor where TPixel : struct, IPixel + public class GetTileAverageProcessor : IImageProcessor where TPixel : unmanaged, IPixel { /// /// The source instance to modify @@ -56,7 +56,7 @@ public class GetTileAverageProcessor : IImageProcessor where TPi /// The defining the processor parameters /// The source for the current processor instance /// The source area to process for the current processor instance - public GetTileAverageProcessor(GetTileAverageProcessor definition, Image source, Rectangle sourceRectangle) + public GetTileAverageProcessor(Configuration configuration, GetTileAverageProcessor definition, Image source, Rectangle sourceRectangle) { _source = source; @@ -70,7 +70,7 @@ public GetTileAverageProcessor(GetTileAverageProcessor definition, Image } /// - public void Apply() + public void Execute() { _resizedImage.Mutate(x => x.Resize(_width, _height)); diff --git a/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs b/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs index d980341..d99e785 100644 --- a/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs @@ -1,10 +1,11 @@ using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; using System; using System.Threading.Tasks; +using Rectangle = SixLabors.ImageSharp.Rectangle; +using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp.Processors { @@ -26,13 +27,13 @@ public GetTilesAverageProcessor(int tX, int tY, Size tileSize, Rgba32[,] avgsMas } /// - public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) where TPixel : struct, IPixel + public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel { - return new GetTilesAverageProcessor(this, source, sourceRectangle); + return new GetTilesAverageProcessor(configuration, this, source, sourceRectangle); } } - public class GetTilesAverageProcessor : IImageProcessor where TPixel : struct, IPixel + public class GetTilesAverageProcessor : IImageProcessor where TPixel : unmanaged, IPixel { /// /// The source instance to modify @@ -51,7 +52,7 @@ public class GetTilesAverageProcessor : IImageProcessor where TP /// The defining the processor parameters /// The source for the current processor instance /// The source area to process for the current processor instance - public GetTilesAverageProcessor(GetTilesAverageProcessor definition, Image source, Rectangle sourceRectangle) + public GetTilesAverageProcessor(Configuration configuration, GetTilesAverageProcessor definition, Image source, Rectangle sourceRectangle) { _source = source; @@ -63,7 +64,7 @@ public GetTilesAverageProcessor(GetTilesAverageProcessor definition, Image - public void Apply() + public void Execute() { Parallel.For(0, _tY, y => { diff --git a/Yugen.Mosaic.Uwp/Processors/PlainColorProcessor.cs b/Yugen.Mosaic.Uwp/Processors/PlainColorProcessor.cs index 07c6af7..54e989a 100644 --- a/Yugen.Mosaic.Uwp/Processors/PlainColorProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/PlainColorProcessor.cs @@ -1,8 +1,6 @@ using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Primitives; using System.Numerics; using System.Runtime.CompilerServices; using System.Threading.Tasks; @@ -11,27 +9,26 @@ namespace Yugen.Mosaic.Uwp.Processors { public sealed class PlainColorProcessor : IImageProcessor { - public Rgba32 AverageColor { get; } - public PlainColorProcessor(Rgba32 averageColor) { AverageColor = averageColor; } - /// - public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) where TPixel : struct, IPixel - { - return new PlainColorProcessor(this, source, sourceRectangle); + public Rgba32 AverageColor { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel + { + return new PlainColorProcessor(configuration, this, source, sourceRectangle); } } - public class PlainColorProcessor : IImageProcessor where TPixel : struct, IPixel + public class PlainColorProcessor : IImageProcessor where TPixel : unmanaged, IPixel { /// /// The source instance to modify /// private readonly Image _source; - private readonly Rgba32 _averageColor; /// @@ -40,14 +37,13 @@ public class PlainColorProcessor : IImageProcessor where TPixel /// The defining the processor parameters /// The source for the current processor instance /// The source area to process for the current processor instance - public PlainColorProcessor(PlainColorProcessor definition, Image source, Rectangle sourceRectangle) + public PlainColorProcessor(Configuration configuration, PlainColorProcessor definition, Image source, Rectangle sourceRectangle) { _source = source; _averageColor = definition.AverageColor; } - /// - public void Apply() + public void Execute() { int width = _source.Width; Image source = _source; @@ -75,3 +71,5 @@ public void Apply() public void Dispose() { } } } + + diff --git a/Yugen.Mosaic.Uwp/Services/MosaicService.cs b/Yugen.Mosaic.Uwp/Services/MosaicService.cs index 133ac21..7714541 100644 --- a/Yugen.Mosaic.Uwp/Services/MosaicService.cs +++ b/Yugen.Mosaic.Uwp/Services/MosaicService.cs @@ -11,6 +11,7 @@ using Windows.UI.Xaml.Media.Imaging; using Yugen.Mosaic.Uwp.Models; using Yugen.Mosaic.Uwp.Processors; +using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp.Services { diff --git a/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs b/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs index f7e0d2e..bb3bbb7 100644 --- a/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs +++ b/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs @@ -21,6 +21,7 @@ using Yugen.Mosaic.Uwp.Services; using Yugen.Toolkit.Uwp.Helpers; using Yugen.Toolkit.Uwp.ViewModels; +using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp { diff --git a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj index 0152245..3bf12f5 100644 --- a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj +++ b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj @@ -233,13 +233,13 @@ - 3.0.0 + 3.2.1 - 3.0.0 + 3.2.1 - 6.2.9 + 6.2.10 6.0.0 @@ -254,7 +254,7 @@ 2.3.200213001 - 1.0.0-beta0007 + 1.0.0-rc0001 1.0.0-beta0007 @@ -263,13 +263,13 @@ 1.6.5 - 1.0.20 + 1.0.22 - 1.0.20 + 1.0.22 - 1.0.20 + 1.0.22 From b96296607b418aaa53244feea966261787e5bc0a Mon Sep 17 00:00:00 2001 From: Emiliano Magliocca Date: Sun, 3 May 2020 16:00:38 +0300 Subject: [PATCH 2/7] Work on ApplyTileFoundProcessor --- .../Processors/AdjustHueProcessor.cs | 1 - .../Processors/ApplyTileFoundProcessor.cs | 1 - .../Processors/GetTileAverageProcessor.cs | 1 - .../Processors/GetTilesAverageProcessor.cs | 1 - Yugen.Mosaic.Uwp/Services/MosaicService.cs | 34 +++++++++++++++++-- Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs | 1 - Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj | 2 +- 7 files changed, 32 insertions(+), 9 deletions(-) diff --git a/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs b/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs index e39ebac..143afa3 100644 --- a/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs @@ -1,7 +1,6 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Primitives; using System; using System.Threading.Tasks; using Rectangle = SixLabors.ImageSharp.Rectangle; diff --git a/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs b/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs index 44b8b31..793e32f 100644 --- a/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs @@ -1,7 +1,6 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Primitives; using System.Threading.Tasks; using Rectangle = SixLabors.ImageSharp.Rectangle; diff --git a/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs b/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs index da544b2..4941e3f 100644 --- a/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs @@ -2,7 +2,6 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Primitives; using System; using System.Threading.Tasks; using Rectangle = SixLabors.ImageSharp.Rectangle; diff --git a/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs b/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs index d99e785..5948e47 100644 --- a/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs @@ -1,7 +1,6 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Primitives; using System; using System.Threading.Tasks; using Rectangle = SixLabors.ImageSharp.Rectangle; diff --git a/Yugen.Mosaic.Uwp/Services/MosaicService.cs b/Yugen.Mosaic.Uwp/Services/MosaicService.cs index 7714541..6ba7ed9 100644 --- a/Yugen.Mosaic.Uwp/Services/MosaicService.cs +++ b/Yugen.Mosaic.Uwp/Services/MosaicService.cs @@ -1,11 +1,11 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -using SixLabors.Primitives; using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Numerics; using System.Threading.Tasks; using Windows.Storage.Streams; using Windows.UI.Xaml.Media.Imaging; @@ -168,10 +168,28 @@ private void SearchAndReplaceClassic(Image outputImage, Size tileSize) var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); tileFound.ResizedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); + //this.ApplyTileFoundProcessor(x, y, tileFound.ResizedImage, outputImage); + _progress++; }); } + private void ApplyTileFoundProcessor(int x, int y, Image source, Image destination) + { + destination.Mutate(c => + { + //for (int h = 0; h < _tY; h++) + //{ + // for (int w = 0; w < _tX; w++) + // { + var point = new Point(x * source.Width, y * source.Height); + + c.DrawImage(source, point, 1); + // } + //} + }); + } + // Don't adjust hue - keep searching for a tile close enough private void SearchAndReplaceRandom(Image outputImage, Size tileSize) { @@ -264,8 +282,18 @@ private void PlainColor(Image outputImage, Size tileSize) // Generate colored tile Image adjustedImage = new Image(tileSize.Width, tileSize.Height); - var plainColorProcessor = new PlainColorProcessor(_avgsMaster[x, y]); - adjustedImage.Mutate(c => c.ApplyProcessor(plainColorProcessor)); + //var plainColorProcessor = new PlainColorProcessor(_avgsMaster[x, y]); + //adjustedImage.Mutate(c => c.ApplyProcessor(plainColorProcessor)); + + Vector4 averageColor4 = _avgsMaster[x, y].ToVector4(); + + adjustedImage.Mutate(c => c.ProcessPixelRowsAsVector4(row => + { + foreach (ref Vector4 pixel in row) + { + pixel = (pixel + averageColor4) / 2; + } + })); // Apply found tile to section var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); diff --git a/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs b/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs index bb3bbb7..5f7bf04 100644 --- a/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs +++ b/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs @@ -1,7 +1,6 @@ using Microsoft.Toolkit.Uwp.Helpers; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; using System; using System.Collections.Generic; using System.Collections.ObjectModel; diff --git a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj index 3bf12f5..91519f6 100644 --- a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj +++ b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj @@ -257,7 +257,7 @@ 1.0.0-rc0001 - 1.0.0-beta0007 + 1.0.0-unstable0436 1.6.5 From 255e77002fee7047e09037c31a9386906c7f34e3 Mon Sep 17 00:00:00 2001 From: Emiliano Magliocca Date: Sun, 3 May 2020 17:15:46 +0300 Subject: [PATCH 3/7] Move Onboarding strings to strings Refactoring --- Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs | 81 +++------ Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs | 14 ++ Yugen.Mosaic.Uwp/Models/OnboardingElement.cs | 24 +++ Yugen.Mosaic.Uwp/Models/OnboardingStage.cs | 13 ++ Yugen.Mosaic.Uwp/Strings/en-US/Resources.resw | 162 ++++++++++++++++++ Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs | 1 + Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj | 10 +- 7 files changed, 244 insertions(+), 61 deletions(-) create mode 100644 Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs create mode 100644 Yugen.Mosaic.Uwp/Models/OnboardingElement.cs create mode 100644 Yugen.Mosaic.Uwp/Models/OnboardingStage.cs create mode 100644 Yugen.Mosaic.Uwp/Strings/en-US/Resources.resw diff --git a/Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs b/Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs index 960c771..dcfc7dc 100644 --- a/Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs +++ b/Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs @@ -1,37 +1,9 @@ using Windows.UI.Xaml; using Yugen.Mosaic.Uwp.Extensions; +using Yugen.Mosaic.Uwp.Models; namespace Yugen.Mosaic.Uwp.Helpers { - public enum OnboardingStage - { - MasterImage, - AddTiles, - TileProperties, - MosaicType, - OutputProperties, - Generate, - Save - } - - public class OnboardingElement - { - public string Title { get; set; } - - public string Subtitle { get; set; } - - public FrameworkElement Target { get; set; } - - public OnboardingStage Stage { get; set; } - - public OnboardingElement(string title, string subtitle, FrameworkElement target, OnboardingStage stage) - { - Title = title; - Subtitle = subtitle; - Target = target; - Stage = stage; - } - } public static class OnboardingHelper { @@ -48,38 +20,29 @@ public static bool IsDisabled public static void Init(FrameworkElement[] frameworkElements) { - var masterImageDescription = "Choose what image you want to use as the Matrix of the mosaic. " + - "Yugen Mosaic will create a mosaic as close as possible to the main image."; - - var addTilesDescription = "Add a list of Tile Images, Yugen Mosaic will use as tiles to build your mosaic"; - - var tilesPropertiesDescription = "After you created the Tile Images List, it is necessary to set all the parameters of the mosaic." + - "Here you can set the size of every single tile"; - - var mosaicTypeDescription = "Choose the tpe of mosaic."; - - var outputDescription = "Choose the size of the mosaic."; - - var generateDescription = "Create the mosaic."; - - var saveDescription = "The last step is to save the mosaic."; - _onboardingElements = new OnboardingElement[] { - new OnboardingElement("Select the Main Image", masterImageDescription, - frameworkElements[0], OnboardingStage.MasterImage), - new OnboardingElement("Create a Tile Images List", addTilesDescription, - frameworkElements[1], OnboardingStage.AddTiles), - new OnboardingElement("TileProperties", tilesPropertiesDescription, - frameworkElements[2], OnboardingStage.TileProperties), - new OnboardingElement("MosaicType", mosaicTypeDescription, - frameworkElements[3], OnboardingStage.MosaicType), - new OnboardingElement("Set the parameters of the Mosaic", outputDescription, - frameworkElements[4], OnboardingStage.OutputProperties), - new OnboardingElement("Create the Mosaic", generateDescription, - frameworkElements[5], OnboardingStage.Generate), - new OnboardingElement("Save the Mosaic", saveDescription, - frameworkElements[6], OnboardingStage.Save), + new OnboardingElement( + frameworkElements[0], + OnboardingStage.MasterImage), + new OnboardingElement( + frameworkElements[1], + OnboardingStage.AddTiles), + new OnboardingElement( + frameworkElements[2], + OnboardingStage.TileProperties), + new OnboardingElement( + frameworkElements[3], + OnboardingStage.MosaicType), + new OnboardingElement( + frameworkElements[4], + OnboardingStage.OutputProperties), + new OnboardingElement( + frameworkElements[5], + OnboardingStage.Generate), + new OnboardingElement( + frameworkElements[6], + OnboardingStage.Save), }; } diff --git a/Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs b/Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs new file mode 100644 index 0000000..5a1301b --- /dev/null +++ b/Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs @@ -0,0 +1,14 @@ +using Windows.ApplicationModel.Resources; + +namespace Yugen.Mosaic.Uwp.Helpers +{ + public static class ResourceHelper + { + private static readonly ResourceLoader _resourceLoader = _resourceLoader ?? new ResourceLoader(); + + public static string GetText(string key) + { + return _resourceLoader.GetString(key); + } + } +} \ No newline at end of file diff --git a/Yugen.Mosaic.Uwp/Models/OnboardingElement.cs b/Yugen.Mosaic.Uwp/Models/OnboardingElement.cs new file mode 100644 index 0000000..1d7a3d4 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Models/OnboardingElement.cs @@ -0,0 +1,24 @@ +using Windows.UI.Xaml; +using Yugen.Mosaic.Uwp.Helpers; + +namespace Yugen.Mosaic.Uwp.Models +{ + public class OnboardingElement + { + public string Title { get; set; } + + public string Subtitle { get; set; } + + public FrameworkElement Target { get; set; } + + public OnboardingStage Stage { get; set; } + + public OnboardingElement(FrameworkElement target, OnboardingStage stage) + { + Title = ResourceHelper.GetText($"OnboardingStage{stage}Title"); + Subtitle = ResourceHelper.GetText($"OnboardingStage{stage}Description"); + Target = target; + Stage = stage; + } + } +} \ No newline at end of file diff --git a/Yugen.Mosaic.Uwp/Models/OnboardingStage.cs b/Yugen.Mosaic.Uwp/Models/OnboardingStage.cs new file mode 100644 index 0000000..db40c69 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Models/OnboardingStage.cs @@ -0,0 +1,13 @@ +namespace Yugen.Mosaic.Uwp.Models +{ + public enum OnboardingStage + { + MasterImage, + AddTiles, + TileProperties, + MosaicType, + OutputProperties, + Generate, + Save + } +} \ No newline at end of file diff --git a/Yugen.Mosaic.Uwp/Strings/en-US/Resources.resw b/Yugen.Mosaic.Uwp/Strings/en-US/Resources.resw new file mode 100644 index 0000000..b7510e5 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Strings/en-US/Resources.resw @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Add a list of Tile Images, Yugen Mosaic will use as tiles to build your mosaic + + + Create a Tile Images List + + + Create the mosaic. + + + Create the Mosaic + + + Choose what image you want to use as the Matrix of the mosaic. Yugen Mosaic will create a mosaic as close as possible to the main image. + + + Select the Main Image + + + Choose the tpe of mosaic. + + + MosaicType + + + Choose the size of the mosaic. + + + Set the parameters of the Mosaic + + + The last step is to save the mosaic. + + + Save the Mosaic + + + After you created the Tile Images List, it is necessary to set all the parameters of the mosaic. Here you can set the size of every single tile + + + TileProperties + + \ No newline at end of file diff --git a/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs b/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs index 8d28e5c..0a3ecff 100644 --- a/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs +++ b/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs @@ -389,6 +389,7 @@ public void ShowTeachingTip() { var onboardingElement = OnboardingHelper.ShowTeachingTip(); if (onboardingElement == null) return; + TeachingTipTitle = onboardingElement.Title; TeachingTipSubTitle = onboardingElement.Subtitle; TeachingTipTarget = onboardingElement.Target; diff --git a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj index 1b8684e..a5ebcab 100644 --- a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj +++ b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj @@ -18,7 +18,8 @@ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} true False - + + False SHA256 True @@ -137,7 +138,10 @@ + + + MainPage.xaml @@ -274,7 +278,9 @@ 1.0.22 - + + + 14.0 From 6bf269aeb196b83c6ad15e6379fffaa088467bd4 Mon Sep 17 00:00:00 2001 From: Emiliano Magliocca Date: Sun, 3 May 2020 18:23:12 +0300 Subject: [PATCH 4/7] Refactor proessors --- .../Processors/AdjustHueProcessor.cs | 136 +++++------ .../Processors/GetTileAverageProcessor.cs | 208 ++++++++-------- .../Processors/GetTilesAverageProcessor.cs | 222 +++++++++--------- Yugen.Mosaic.Uwp/Services/MosaicService.cs | 126 ++++++++-- 4 files changed, 392 insertions(+), 300 deletions(-) diff --git a/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs b/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs index 143afa3..021d07d 100644 --- a/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs @@ -1,80 +1,80 @@ -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors; -using System; -using System.Threading.Tasks; -using Rectangle = SixLabors.ImageSharp.Rectangle; +//using SixLabors.ImageSharp; +//using SixLabors.ImageSharp.PixelFormats; +//using SixLabors.ImageSharp.Processing.Processors; +//using System; +//using System.Threading.Tasks; +//using Rectangle = SixLabors.ImageSharp.Rectangle; -namespace Yugen.Mosaic.Uwp.Processors -{ - public sealed class AdjustHueProcessor : IImageProcessor - { - public Image InputImage { get; } - public Rgba32 AverageColor { get; } +//namespace Yugen.Mosaic.Uwp.Processors +//{ +// public sealed class AdjustHueProcessor : IImageProcessor +// { +// public Image InputImage { get; } +// public Rgba32 AverageColor { get; } - public AdjustHueProcessor(Image inputImage, Rgba32 averageColor) - { - InputImage = inputImage; - AverageColor = averageColor; - } +// public AdjustHueProcessor(Image inputImage, Rgba32 averageColor) +// { +// InputImage = inputImage; +// AverageColor = averageColor; +// } - /// - public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel - { - return new AdjustHueProcessor(configuration, this, source, sourceRectangle); - } - } +// /// +// public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel +// { +// return new AdjustHueProcessor(configuration, this, source, sourceRectangle); +// } +// } - public class AdjustHueProcessor : IImageProcessor where TPixel : unmanaged, IPixel - { - /// - /// The source instance to modify - /// - private readonly Image _source; - private readonly Image _inputImage; - private readonly Rgba32 _averageColor; +// public class AdjustHueProcessor : IImageProcessor where TPixel : unmanaged, IPixel +// { +// /// +// /// The source instance to modify +// /// +// private readonly Image _source; +// private readonly Image _inputImage; +// private readonly Rgba32 _averageColor; - /// - /// Initializes a new instance of the class - /// - /// The defining the processor parameters - /// The source for the current processor instance - /// The source area to process for the current processor instance - public AdjustHueProcessor(Configuration configuration, AdjustHueProcessor definition, Image source, Rectangle sourceRectangle) - { - _source = source; - _inputImage = definition.InputImage; - _averageColor = definition.AverageColor; - } +// /// +// /// Initializes a new instance of the class +// /// +// /// The defining the processor parameters +// /// The source for the current processor instance +// /// The source area to process for the current processor instance +// public AdjustHueProcessor(Configuration configuration, AdjustHueProcessor definition, Image source, Rectangle sourceRectangle) +// { +// _source = source; +// _inputImage = definition.InputImage; +// _averageColor = definition.AverageColor; +// } - /// - public void Execute() - { - //int width = Source.Width; - //Image source = Source; +// /// +// public void Execute() +// { +// //int width = Source.Width; +// //Image source = Source; - Parallel.For(0, _inputImage.Height, h => - { - var rowSpan = _inputImage.GetPixelRowSpan(h); +// Parallel.For(0, _inputImage.Height, h => +// { +// var rowSpan = _inputImage.GetPixelRowSpan(h); - for (int w = 0; w < _inputImage.Width; w++) - { - Rgba32 pixel = new Rgba32(); - rowSpan[w].ToRgba32(ref pixel); +// for (int w = 0; w < _inputImage.Width; w++) +// { +// Rgba32 pixel = new Rgba32(); +// rowSpan[w].ToRgba32(ref pixel); - int R = Math.Min(255, Math.Max(0, (pixel.R + _averageColor.R) / 2)); - int G = Math.Min(255, Math.Max(0, (pixel.G + _averageColor.G) / 2)); - int B = Math.Min(255, Math.Max(0, (pixel.B + _averageColor.B) / 2)); +// int R = Math.Min(255, Math.Max(0, (pixel.R + _averageColor.R) / 2)); +// int G = Math.Min(255, Math.Max(0, (pixel.G + _averageColor.G) / 2)); +// int B = Math.Min(255, Math.Max(0, (pixel.B + _averageColor.B) / 2)); - Color clAvg = new Rgba32(Convert.ToByte(R), Convert.ToByte(G), Convert.ToByte(B)); +// Color clAvg = new Rgba32(Convert.ToByte(R), Convert.ToByte(G), Convert.ToByte(B)); - TPixel pixelColor = clAvg.ToPixel(); - _source[w, h] = pixelColor; - } - }); - } +// TPixel pixelColor = clAvg.ToPixel(); +// _source[w, h] = pixelColor; +// } +// }); +// } - /// - public void Dispose() { } - } -} +// /// +// public void Dispose() { } +// } +//} diff --git a/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs b/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs index 4941e3f..9a73c4a 100644 --- a/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs @@ -1,105 +1,105 @@ -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors; -using System; -using System.Threading.Tasks; -using Rectangle = SixLabors.ImageSharp.Rectangle; - -namespace Yugen.Mosaic.Uwp.Processors -{ - public sealed class GetTileAverageProcessor : IImageProcessor - { - public int X { get; } - public int Y { get; } - public int Width { get; } - public int Height { get; } - - public Image ResizedImage { get; } - public Rgba32[] AverageColor { get; } = new Rgba32[1]; - - public GetTileAverageProcessor(int x, int y, int width, int height, Image resizedImage) - { - X = x; - Y = y; - Width = width; - Height = height; - ResizedImage = resizedImage.CloneAs(); - } - - /// - public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel - { - return new GetTileAverageProcessor(configuration, this, source, sourceRectangle); - } - } - - public class GetTileAverageProcessor : IImageProcessor where TPixel : unmanaged, IPixel - { - /// - /// The source instance to modify - /// - private readonly Image _source; - - private readonly int _x; - private readonly int _y; - private readonly int _width; - private readonly int _height; - - private readonly Image _resizedImage; - private readonly Rgba32[] _averageColor; - - /// - /// Initializes a new instance of the class - /// - /// The defining the processor parameters - /// The source for the current processor instance - /// The source area to process for the current processor instance - public GetTileAverageProcessor(Configuration configuration, GetTileAverageProcessor definition, Image source, Rectangle sourceRectangle) - { - _source = source; - - _x = definition.X; - _y = definition.Y; - _width = definition.Width; - _height = definition.Height; - - _resizedImage = definition.ResizedImage; - _averageColor = definition.AverageColor; - } +//using SixLabors.ImageSharp; +//using SixLabors.ImageSharp.PixelFormats; +//using SixLabors.ImageSharp.Processing; +//using SixLabors.ImageSharp.Processing.Processors; +//using System; +//using System.Threading.Tasks; +//using Rectangle = SixLabors.ImageSharp.Rectangle; + +//namespace Yugen.Mosaic.Uwp.Processors +//{ +// public sealed class GetTileAverageProcessor : IImageProcessor +// { +// public int X { get; } +// public int Y { get; } +// public int Width { get; } +// public int Height { get; } + +// public Image ResizedImage { get; } +// public Rgba32[] AverageColor { get; } = new Rgba32[1]; + +// public GetTileAverageProcessor(int x, int y, int width, int height, Image resizedImage) +// { +// X = x; +// Y = y; +// Width = width; +// Height = height; +// ResizedImage = resizedImage.CloneAs(); +// } + +// /// +// public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel +// { +// return new GetTileAverageProcessor(configuration, this, source, sourceRectangle); +// } +// } + +// public class GetTileAverageProcessor : IImageProcessor where TPixel : unmanaged, IPixel +// { +// /// +// /// The source instance to modify +// /// +// private readonly Image _source; + +// private readonly int _x; +// private readonly int _y; +// private readonly int _width; +// private readonly int _height; + +// private readonly Image _resizedImage; +// private readonly Rgba32[] _averageColor; + +// /// +// /// Initializes a new instance of the class +// /// +// /// The defining the processor parameters +// /// The source for the current processor instance +// /// The source area to process for the current processor instance +// public GetTileAverageProcessor(Configuration configuration, GetTileAverageProcessor definition, Image source, Rectangle sourceRectangle) +// { +// _source = source; + +// _x = definition.X; +// _y = definition.Y; +// _width = definition.Width; +// _height = definition.Height; + +// _resizedImage = definition.ResizedImage; +// _averageColor = definition.AverageColor; +// } - /// - public void Execute() - { - _resizedImage.Mutate(x => x.Resize(_width, _height)); - - long aR = 0; - long aG = 0; - long aB = 0; - - Parallel.For(_y, _y+_height, h => - { - var rowSpan = _resizedImage.GetPixelRowSpan(h); - - for (int w = _x; w < _x + _width; w++) - { - Rgba32 pixel = new Rgba32(); - rowSpan[w].ToRgba32(ref pixel); - - aR += pixel.R; - aG += pixel.G; - aB += pixel.B; - } - }); - - aR /= _width * _height; - aG /= _width * _height; - aB /= _width * _height; - - _averageColor[0] = new Rgba32(Convert.ToByte(aR), Convert.ToByte(aG), Convert.ToByte(aB)); - } - - /// - public void Dispose() { } - } -} +// /// +// public void Execute() +// { +// _resizedImage.Mutate(x => x.Resize(_width, _height)); + +// long aR = 0; +// long aG = 0; +// long aB = 0; + +// Parallel.For(_y, _y+_height, h => +// { +// var rowSpan = _resizedImage.GetPixelRowSpan(h); + +// for (int w = _x; w < _x + _width; w++) +// { +// Rgba32 pixel = new Rgba32(); +// rowSpan[w].ToRgba32(ref pixel); + +// aR += pixel.R; +// aG += pixel.G; +// aB += pixel.B; +// } +// }); + +// aR /= _width * _height; +// aG /= _width * _height; +// aB /= _width * _height; + +// _averageColor[0] = new Rgba32(Convert.ToByte(aR), Convert.ToByte(aG), Convert.ToByte(aB)); +// } + +// /// +// public void Dispose() { } +// } +//} diff --git a/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs b/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs index 5948e47..afed0ce 100644 --- a/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs @@ -1,111 +1,111 @@ -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors; -using System; -using System.Threading.Tasks; -using Rectangle = SixLabors.ImageSharp.Rectangle; -using Size = SixLabors.ImageSharp.Size; - -namespace Yugen.Mosaic.Uwp.Processors -{ - public sealed class GetTilesAverageProcessor : IImageProcessor - { - public int TX { get; } - public int TY { get; } - public Size TileSize { get; } - - public Rgba32[,] AverageColors { get; } - - public GetTilesAverageProcessor(int tX, int tY, Size tileSize, Rgba32[,] avgsMaster) - { - TX = tX; - TY = tY; - TileSize = tileSize; - - AverageColors = avgsMaster; - } - - /// - public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel - { - return new GetTilesAverageProcessor(configuration, this, source, sourceRectangle); - } - } - - public class GetTilesAverageProcessor : IImageProcessor where TPixel : unmanaged, IPixel - { - /// - /// The source instance to modify - /// - private readonly Image _source; - - private readonly int _tX; - private readonly int _tY; - private Size _tileSize; - - private readonly Rgba32[,] _averageColors; - - /// - /// Initializes a new instance of the class - /// - /// The defining the processor parameters - /// The source for the current processor instance - /// The source area to process for the current processor instance - public GetTilesAverageProcessor(Configuration configuration, GetTilesAverageProcessor definition, Image source, Rectangle sourceRectangle) - { - _source = source; - - _tX = definition.TX; - _tY = definition.TY; - _tileSize = definition.TileSize; - - _averageColors = definition.AverageColors; - } - - /// - public void Execute() - { - Parallel.For(0, _tY, y => - { - var rowSpan = _source.GetPixelRowSpan(y); - - for (int x = 0; x < _tX; x++) - { - _averageColors[x, y].FromRgba32(GetTileAverage(_source, x * _tileSize.Width, y * _tileSize.Height, _tileSize.Width, _tileSize.Height)); - } - }); - } - - private Rgba32 GetTileAverage(Image source, int x, int y, int width, int height) - { - long aR = 0; - long aG = 0; - long aB = 0; - - Parallel.For(y, y + height, h => - { - var rowSpan = _source.GetPixelRowSpan(h); - - for (int w = x; w < x + width; w++) - { - Rgba32 pixel = new Rgba32(); - rowSpan[w].ToRgba32(ref pixel); - - aR += pixel.R; - aG += pixel.G; - aB += pixel.B; - } - }); - - aR /= width * height; - aG /= width * height; - aB /= width * height; - - return new Rgba32(Convert.ToByte(aR), Convert.ToByte(aG), Convert.ToByte(aB)); - } - - - /// - public void Dispose() { } - } -} +//using SixLabors.ImageSharp; +//using SixLabors.ImageSharp.PixelFormats; +//using SixLabors.ImageSharp.Processing.Processors; +//using System; +//using System.Threading.Tasks; +//using Rectangle = SixLabors.ImageSharp.Rectangle; +//using Size = SixLabors.ImageSharp.Size; + +//namespace Yugen.Mosaic.Uwp.Processors +//{ +// public sealed class GetTilesAverageProcessor : IImageProcessor +// { +// public int TX { get; } +// public int TY { get; } +// public Size TileSize { get; } + +// public Rgba32[,] AverageColors { get; } + +// public GetTilesAverageProcessor(int tX, int tY, Size tileSize, Rgba32[,] avgsMaster) +// { +// TX = tX; +// TY = tY; +// TileSize = tileSize; + +// AverageColors = avgsMaster; +// } + +// /// +// public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel +// { +// return new GetTilesAverageProcessor(configuration, this, source, sourceRectangle); +// } +// } + +// public class GetTilesAverageProcessor : IImageProcessor where TPixel : unmanaged, IPixel +// { +// /// +// /// The source instance to modify +// /// +// private readonly Image _source; + +// private readonly int _tX; +// private readonly int _tY; +// private Size _tileSize; + +// private readonly Rgba32[,] _averageColors; + +// /// +// /// Initializes a new instance of the class +// /// +// /// The defining the processor parameters +// /// The source for the current processor instance +// /// The source area to process for the current processor instance +// public GetTilesAverageProcessor(Configuration configuration, GetTilesAverageProcessor definition, Image source, Rectangle sourceRectangle) +// { +// _source = source; + +// _tX = definition.TX; +// _tY = definition.TY; +// _tileSize = definition.TileSize; + +// _averageColors = definition.AverageColors; +// } + +// /// +// public void Execute() +// { +// Parallel.For(0, _tY, y => +// { +// var rowSpan = _source.GetPixelRowSpan(y); + +// for (int x = 0; x < _tX; x++) +// { +// _averageColors[x, y].FromRgba32(GetTileAverage(_source, x * _tileSize.Width, y * _tileSize.Height, _tileSize.Width, _tileSize.Height)); +// } +// }); +// } + +// private Rgba32 GetTileAverage(Image source, int x, int y, int width, int height) +// { +// long aR = 0; +// long aG = 0; +// long aB = 0; + +// Parallel.For(y, y + height, h => +// { +// var rowSpan = _source.GetPixelRowSpan(h); + +// for (int w = x; w < x + width; w++) +// { +// Rgba32 pixel = new Rgba32(); +// rowSpan[w].ToRgba32(ref pixel); + +// aR += pixel.R; +// aG += pixel.G; +// aB += pixel.B; +// } +// }); + +// aR /= width * height; +// aG /= width * height; +// aB /= width * height; + +// return new Rgba32(Convert.ToByte(aR), Convert.ToByte(aG), Convert.ToByte(aB)); +// } + + +// /// +// public void Dispose() { } +// } +//} diff --git a/Yugen.Mosaic.Uwp/Services/MosaicService.cs b/Yugen.Mosaic.Uwp/Services/MosaicService.cs index 2b3a3ba..5dfd74f 100644 --- a/Yugen.Mosaic.Uwp/Services/MosaicService.cs +++ b/Yugen.Mosaic.Uwp/Services/MosaicService.cs @@ -94,10 +94,49 @@ public Image GenerateMosaic(Size outputSize, Size tileSize, int mosaicTy private void GetTilesAverage(Image masterImage) { - var getTilesAverageProcessor = new GetTilesAverageProcessor(_tX, _tY, _tileSize, _avgsMaster); - masterImage.Mutate(c => c.ApplyProcessor(getTilesAverageProcessor)); + //var getTilesAverageProcessor = new GetTilesAverageProcessor(_tX, _tY, _tileSize, _avgsMaster); + //masterImage.Mutate(c => c.ApplyProcessor(getTilesAverageProcessor)); + + Parallel.For(0, _tY, y => + { + var rowSpan = masterImage.GetPixelRowSpan(y); + + for (int x = 0; x < _tX; x++) + { + _avgsMaster[x, y].FromRgba32(GetTileAverage(masterImage, x * _tileSize.Width, y * _tileSize.Height, _tileSize.Width, _tileSize.Height)); + } + }); } + private Rgba32 GetTileAverage(Image source, int x, int y, int width, int height) + { + long aR = 0; + long aG = 0; + long aB = 0; + + Parallel.For(y, y + height, h => + { + var rowSpan = source.GetPixelRowSpan(h); + + for (int w = x; w < x + width; w++) + { + Rgba32 pixel = new Rgba32(); + rowSpan[w].ToRgba32(ref pixel); + + aR += pixel.R; + aG += pixel.G; + aB += pixel.B; + } + }); + + aR /= width * height; + aG /= width * height; + aB /= width * height; + + return new Rgba32(Convert.ToByte(aR), Convert.ToByte(aG), Convert.ToByte(aB)); + } + + private void LoadTilesAndResize() { _progressMax = _tileImageList.Count; @@ -105,16 +144,47 @@ private void LoadTilesAndResize() foreach (var tile in _tileImageList) { - var getTileAverageProcessor = new GetTileAverageProcessor(0, 0, _tileSize.Width, _tileSize.Height, tile.OriginalImage); - tile.OriginalImage.Mutate(c => c.ApplyProcessor(getTileAverageProcessor)); + //var getTileAverageProcessor = new GetTileAverageProcessor(0, 0, _tileSize.Width, _tileSize.Height, tile.OriginalImage); + //tile.OriginalImage.Mutate(c => c.ApplyProcessor(getTileAverageProcessor)); + //tile.ResizedImage = getTileAverageProcessor.ResizedImage; + //tile.AverageColor = getTileAverageProcessor.AverageColor[0]; - tile.ResizedImage = getTileAverageProcessor.ResizedImage; - tile.AverageColor = getTileAverageProcessor.AverageColor[0]; + tile.ResizedImage = tile.OriginalImage.CloneAs(); ; + tile.ResizedImage.Mutate(x => x.Resize(_tileSize.Width, _tileSize.Height)); + tile.AverageColor = GetAverageColor(tile.ResizedImage); _progress++; } } + private Rgba32 GetAverageColor(Image source) + { + long aR = 0; + long aG = 0; + long aB = 0; + + Parallel.For(0, source.Height, h => + { + var rowSpan = source.GetPixelRowSpan(h); + + for (int w = 0; w < source.Width; w++) + { + Rgba32 pixel = new Rgba32(); + rowSpan[w].ToRgba32(ref pixel); + + aR += pixel.R; + aG += pixel.G; + aB += pixel.B; + } + }); + + aR /= source.Width * source.Height; + aG /= source.Width * source.Height; + aB /= source.Width * source.Height; + + return new Rgba32(Convert.ToByte(aR), Convert.ToByte(aG), Convert.ToByte(aB)); + } + private void SearchAndReplace(Image outputImage, Size tileSize, int mosaicType) { @@ -178,15 +248,8 @@ private void ApplyTileFoundProcessor(int x, int y, Image source, Image { - //for (int h = 0; h < _tY; h++) - //{ - // for (int w = 0; w < _tX; w++) - // { - var point = new Point(x * source.Width, y * source.Height); - - c.DrawImage(source, point, 1); - // } - //} + var point = new Point(x * source.Width, y * source.Height); + c.DrawImage(source, point, 1); }); } @@ -264,8 +327,11 @@ private void SearchAndReplaceAdjustHue(Image outputImage, Size tileSize) // Adjust the hue Image adjustedImage = new Image(tileFound.ResizedImage.Width, tileFound.ResizedImage.Height); - var adjustHueProcessor = new AdjustHueProcessor(tileFound.ResizedImage, _avgsMaster[x, y]); - adjustedImage.Mutate(c => c.ApplyProcessor(adjustHueProcessor)); + + //var adjustHueProcessor = new AdjustHueProcessor(tileFound.ResizedImage, _avgsMaster[x, y]); + //adjustedImage.Mutate(c => c.ApplyProcessor(adjustHueProcessor)); + + AdjustHue(tileFound.ResizedImage, adjustedImage, _avgsMaster[x, y]); // Apply found tile to section //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); @@ -277,6 +343,32 @@ private void SearchAndReplaceAdjustHue(Image outputImage, Size tileSize) }); } + private void AdjustHue(Image source, Image output, Rgba32 averageColor) + { + output.Mutate(c => + { + Parallel.For(0, source.Height, h => + { + var rowSpan = source.GetPixelRowSpan(h); + + for (int w = 0; w < source.Width; w++) + { + Rgba32 pixel = new Rgba32(); + rowSpan[w].ToRgba32(ref pixel); + + int R = Math.Min(255, Math.Max(0, (pixel.R + averageColor.R) / 2)); + int G = Math.Min(255, Math.Max(0, (pixel.G + averageColor.G) / 2)); + int B = Math.Min(255, Math.Max(0, (pixel.B + averageColor.B) / 2)); + + Color clAvg = new Rgba32(Convert.ToByte(R), Convert.ToByte(G), Convert.ToByte(B)); + + Rgba32 pixelColor = clAvg.ToPixel(); + output[w, h] = pixelColor; + } + }); + }); + } + // Use just mosic colored tiles private void PlainColor(Image outputImage, Size tileSize) { From b5d0a07199c21233be865cd062add99e4d91dc3c Mon Sep 17 00:00:00 2001 From: Emiliano Magliocca Date: Mon, 4 May 2020 11:01:08 +0300 Subject: [PATCH 5/7] Refactor --- Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs | 53 ++++ .../Interfaces/ISearchAndReplaceService.cs | 7 + .../AdjustHueSearchAndReplaceService.cs | 92 ++++++ .../ClassicSearchAndReplaceService.cs | 50 +++ Yugen.Mosaic.Uwp/Services/MosaicService.cs | 291 ++---------------- .../PlainColorSearchAndReplaceService.cs | 51 +++ .../Services/RandomSearchAndReplaceService.cs | 60 ++++ .../Services/SearchAndReplaceService.cs | 47 +++ Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj | 7 + 9 files changed, 386 insertions(+), 272 deletions(-) create mode 100644 Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs create mode 100644 Yugen.Mosaic.Uwp/Interfaces/ISearchAndReplaceService.cs create mode 100644 Yugen.Mosaic.Uwp/Services/AdjustHueSearchAndReplaceService.cs create mode 100644 Yugen.Mosaic.Uwp/Services/ClassicSearchAndReplaceService.cs create mode 100644 Yugen.Mosaic.Uwp/Services/PlainColorSearchAndReplaceService.cs create mode 100644 Yugen.Mosaic.Uwp/Services/RandomSearchAndReplaceService.cs create mode 100644 Yugen.Mosaic.Uwp/Services/SearchAndReplaceService.cs diff --git a/Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs b/Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs new file mode 100644 index 0000000..ead3595 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs @@ -0,0 +1,53 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using System; +using System.Threading.Tasks; + +namespace Yugen.Mosaic.Uwp.Helpers +{ + public static class ColorHelper + { + public static Rgba32 GetAverageColor(Image source, int x, int y, Size tileSize) => GetAverageColor(source, x * tileSize.Width, y * tileSize.Height, + tileSize.Width, tileSize.Height, x * tileSize.Width + tileSize.Width, y * tileSize.Height + tileSize.Height); + + public static Rgba32 GetAverageColor(Image source) => GetAverageColor(source, 0, 0, source.Width, source.Height, source.Width, source.Height); + + private static Rgba32 GetAverageColor(Image source, int startX, int startY, int width, int height, int endX, int endY) + { + long aR = 0; + long aG = 0; + long aB = 0; + + Parallel.For(startY, endY, h => + { + var rowSpan = source.GetPixelRowSpan(h); + + for (int w = startX; w < endX; w++) + { + Rgba32 pixel = new Rgba32(); + rowSpan[w].ToRgba32(ref pixel); + + aR += pixel.R; + aG += pixel.G; + aB += pixel.B; + } + }); + + aR /= width * height; + aG /= width * height; + aB /= width * height; + + return new Rgba32(Convert.ToByte(aR), Convert.ToByte(aG), Convert.ToByte(aB)); + } + + + public static int GetDifference(Rgba32 source, Rgba32 target) + { + int dR = Math.Abs(source.R - target.R); + int dG = Math.Abs(source.G - target.G); + int dB = Math.Abs(source.B - target.B); + int diff = Math.Max(dR, dG); + return Math.Max(diff, dB); + } + } +} diff --git a/Yugen.Mosaic.Uwp/Interfaces/ISearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Interfaces/ISearchAndReplaceService.cs new file mode 100644 index 0000000..022c4c8 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Interfaces/ISearchAndReplaceService.cs @@ -0,0 +1,7 @@ +namespace Yugen.Mosaic.Uwp.Interfaces +{ + public interface ISearchAndReplaceService + { + void SearchAndReplace(); + } +} \ No newline at end of file diff --git a/Yugen.Mosaic.Uwp/Services/AdjustHueSearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/AdjustHueSearchAndReplaceService.cs new file mode 100644 index 0000000..d2c8154 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Services/AdjustHueSearchAndReplaceService.cs @@ -0,0 +1,92 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Yugen.Mosaic.Uwp.Models; +using Size = SixLabors.ImageSharp.Size; + +namespace Yugen.Mosaic.Uwp.Services +{ + public class AdjustHueSearchAndReplaceService : SearchAndReplaceService + { + public AdjustHueSearchAndReplaceService(Image outputImage, Size tileSize, int tX, int tY, List tileImageList, Rgba32[,] avgsMaster) : base(outputImage, tileSize, tX, tY, tileImageList, avgsMaster) + { + } + + // Adjust hue - get the first (random) tile found and adjust its colours to suit the average + public override void SearchAndReplace() + { + Random r = new Random(); + List tileQueue = new List(); + //int maxQueueLength = Math.Min(1000, Math.Max(0, _tileImageList.Count - 50)); + + Parallel.For(0, _tX * _tY, xy => + { + int y = xy / _tX; + int x = xy % _tX; + + // (R * ColCount) + C + int index = ((y * _tX) + x) % _tileImageList.Count; + + // Check if it's the same as the last (X)? + //if (tileQueue.Count > 1) + //{ + // while (tileQueue.Contains(_tileImageList[index])) + // { + // index = r.Next(_tileImageList.Count); + // } + //} + + // Add to the 'queue' + Tile tileFound = _tileImageList[index]; + //if (tileQueue.Count >= maxQueueLength && tileQueue.Count > 0) + // tileQueue.RemoveAt(0); + //tileQueue.Add(tileFound); + + // Adjust the hue + Image adjustedImage = new Image(tileFound.ResizedImage.Width, tileFound.ResizedImage.Height); + + //var adjustHueProcessor = new AdjustHueProcessor(tileFound.ResizedImage, _avgsMaster[x, y]); + //adjustedImage.Mutate(c => c.ApplyProcessor(adjustHueProcessor)); + + AdjustHue(tileFound.ResizedImage, adjustedImage, _avgsMaster[x, y]); + + // Apply found tile to section + //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); + //adjustedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); + + this.ApplyTileFoundProcessor(x, y, adjustedImage); + + //_progress++; + }); + } + + private void AdjustHue(Image source, Image output, Rgba32 averageColor) + { + output.Mutate(c => + { + Parallel.For(0, source.Height, h => + { + var rowSpan = source.GetPixelRowSpan(h); + + for (int w = 0; w < source.Width; w++) + { + Rgba32 pixel = new Rgba32(); + rowSpan[w].ToRgba32(ref pixel); + + int R = Math.Min(255, Math.Max(0, (pixel.R + averageColor.R) / 2)); + int G = Math.Min(255, Math.Max(0, (pixel.G + averageColor.G) / 2)); + int B = Math.Min(255, Math.Max(0, (pixel.B + averageColor.B) / 2)); + + Color clAvg = new Rgba32(Convert.ToByte(R), Convert.ToByte(G), Convert.ToByte(B)); + + Rgba32 pixelColor = clAvg.ToPixel(); + output[w, h] = pixelColor; + } + }); + }); + } + } +} diff --git a/Yugen.Mosaic.Uwp/Services/ClassicSearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/ClassicSearchAndReplaceService.cs new file mode 100644 index 0000000..d0a88ed --- /dev/null +++ b/Yugen.Mosaic.Uwp/Services/ClassicSearchAndReplaceService.cs @@ -0,0 +1,50 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using System.Collections.Generic; +using System.Threading.Tasks; +using Yugen.Mosaic.Uwp.Helpers; +using Yugen.Mosaic.Uwp.Models; +using Size = SixLabors.ImageSharp.Size; + +namespace Yugen.Mosaic.Uwp.Services +{ + public class ClassicSearchAndReplaceService : SearchAndReplaceService + { + public ClassicSearchAndReplaceService(Image outputImage, Size tileSize, int tX, int tY, List tileImageList, Rgba32[,] avgsMaster) : base(outputImage, tileSize, tX, tY, tileImageList, avgsMaster) + { + } + + public override void SearchAndReplace() + { + Parallel.For(0, _tX * _tY, xy => + { + int y = xy / _tX; + int x = xy % _tX; + + int index = 0; + int difference = 100; + Tile tileFound = _tileImageList[0]; + + // Search for a tile with a similar color + foreach (var tile in _tileImageList) + { + var newDifference = ColorHelper.GetDifference(_avgsMaster[x, y], _tileImageList[index].AverageColor); + if (newDifference < difference) + { + tileFound = _tileImageList[index]; + difference = newDifference; + } + index++; + } + + // Apply found tile to section + //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); + //tileFound.ResizedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); + + ApplyTileFoundProcessor(x, y, tileFound.ResizedImage); + + //_progress++; + }); + } + } +} diff --git a/Yugen.Mosaic.Uwp/Services/MosaicService.cs b/Yugen.Mosaic.Uwp/Services/MosaicService.cs index 5dfd74f..a5ad72d 100644 --- a/Yugen.Mosaic.Uwp/Services/MosaicService.cs +++ b/Yugen.Mosaic.Uwp/Services/MosaicService.cs @@ -5,12 +5,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Numerics; using System.Threading.Tasks; using Windows.Storage.Streams; using Windows.UI.Xaml.Media.Imaging; +using Yugen.Mosaic.Uwp.Helpers; +using Yugen.Mosaic.Uwp.Interfaces; using Yugen.Mosaic.Uwp.Models; -using Yugen.Mosaic.Uwp.Processors; using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp.Services @@ -19,14 +19,14 @@ public class MosaicService { private Image _masterImage; - private List _tileImageList { get; set; } = new List(); + internal List _tileImageList { get; set; } = new List(); private Size _tileSize; - private int _tX; - private int _tY; - private Rgba32[,] _avgsMaster; + internal int _tX; + internal int _tY; + internal Rgba32[,] _avgsMaster; - private int _progress; + internal int _progress; private int _progressMax; @@ -103,40 +103,11 @@ private void GetTilesAverage(Image masterImage) for (int x = 0; x < _tX; x++) { - _avgsMaster[x, y].FromRgba32(GetTileAverage(masterImage, x * _tileSize.Width, y * _tileSize.Height, _tileSize.Width, _tileSize.Height)); + _avgsMaster[x, y].FromRgba32(ColorHelper.GetAverageColor(masterImage, x, y, _tileSize)); } }); } - private Rgba32 GetTileAverage(Image source, int x, int y, int width, int height) - { - long aR = 0; - long aG = 0; - long aB = 0; - - Parallel.For(y, y + height, h => - { - var rowSpan = source.GetPixelRowSpan(h); - - for (int w = x; w < x + width; w++) - { - Rgba32 pixel = new Rgba32(); - rowSpan[w].ToRgba32(ref pixel); - - aR += pixel.R; - aG += pixel.G; - aB += pixel.B; - } - }); - - aR /= width * height; - aG /= width * height; - aB /= width * height; - - return new Rgba32(Convert.ToByte(aR), Convert.ToByte(aG), Convert.ToByte(aB)); - } - - private void LoadTilesAndResize() { _progressMax = _tileImageList.Count; @@ -151,59 +122,37 @@ private void LoadTilesAndResize() tile.ResizedImage = tile.OriginalImage.CloneAs(); ; tile.ResizedImage.Mutate(x => x.Resize(_tileSize.Width, _tileSize.Height)); - tile.AverageColor = GetAverageColor(tile.ResizedImage); + tile.AverageColor = ColorHelper.GetAverageColor(tile.ResizedImage); _progress++; } } - private Rgba32 GetAverageColor(Image source) - { - long aR = 0; - long aG = 0; - long aB = 0; - - Parallel.For(0, source.Height, h => - { - var rowSpan = source.GetPixelRowSpan(h); - - for (int w = 0; w < source.Width; w++) - { - Rgba32 pixel = new Rgba32(); - rowSpan[w].ToRgba32(ref pixel); - - aR += pixel.R; - aG += pixel.G; - aB += pixel.B; - } - }); - - aR /= source.Width * source.Height; - aG /= source.Width * source.Height; - aB /= source.Width * source.Height; - - return new Rgba32(Convert.ToByte(aR), Convert.ToByte(aG), Convert.ToByte(aB)); - } - private void SearchAndReplace(Image outputImage, Size tileSize, int mosaicType) { _progressMax = _tileImageList.Count; _progress = 0; + ISearchAndReplaceService SearchAndReplaceService; + switch (mosaicType) { case 0: - SearchAndReplaceClassic(outputImage, tileSize); + SearchAndReplaceService = new ClassicSearchAndReplaceService(outputImage, tileSize, _tX, _tY, _tileImageList, _avgsMaster); + SearchAndReplaceService.SearchAndReplace(); break; case 1: - SearchAndReplaceRandom(outputImage, tileSize); + SearchAndReplaceService = new RandomSearchAndReplaceService(outputImage, tileSize, _tX, _tY, _tileImageList, _avgsMaster); + SearchAndReplaceService.SearchAndReplace(); break; case 2: - SearchAndReplaceAdjustHue(outputImage, tileSize); + SearchAndReplaceService = new AdjustHueSearchAndReplaceService(outputImage, tileSize, _tX, _tY, _tileImageList, _avgsMaster); + SearchAndReplaceService.SearchAndReplace(); break; case 3: - PlainColor(outputImage, tileSize); + SearchAndReplaceService = new PlainColorSearchAndReplaceService(outputImage, tileSize, _tX, _tY, _tileImageList, _avgsMaster); + SearchAndReplaceService.SearchAndReplace(); break; } @@ -211,208 +160,6 @@ private void SearchAndReplace(Image outputImage, Size tileSize, int mosa } - private void SearchAndReplaceClassic(Image outputImage, Size tileSize) - { - Parallel.For(0, _tX * _tY, xy => - { - int y = xy / _tX; - int x = xy % _tX; - - int index = 0; - int difference = 100; - Tile tileFound = _tileImageList[0]; - - // Search for a tile with a similar color - foreach (var tile in _tileImageList) - { - var newDifference = GetDifference(_avgsMaster[x, y], _tileImageList[index].AverageColor); - if (newDifference < difference) - { - tileFound = _tileImageList[index]; - difference = newDifference; - } - index++; - } - - // Apply found tile to section - //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); - //tileFound.ResizedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); - - this.ApplyTileFoundProcessor(x, y, tileFound.ResizedImage, outputImage); - - _progress++; - }); - } - - private void ApplyTileFoundProcessor(int x, int y, Image source, Image destination) - { - destination.Mutate(c => - { - var point = new Point(x * source.Width, y * source.Height); - c.DrawImage(source, point, 1); - }); - } - - // Don't adjust hue - keep searching for a tile close enough - private void SearchAndReplaceRandom(Image outputImage, Size tileSize) - { - Random r = new Random(); - - Parallel.For(0, _tX * _tY, xy => - { - int y = xy / _tX; - int x = xy % _tX; - - // Reset searching variables - int threshold = 0; - int searchCounter = 0; - Tile tileFound = null; - - // Search for a tile with a similar color - while (tileFound == null) - { - int index = r.Next(_tileImageList.Count); - var difference = GetDifference(_avgsMaster[x, y], _tileImageList[index].AverageColor); - if (difference < threshold) - { - tileFound = _tileImageList[index]; - } - else - { - searchCounter++; - if (searchCounter >= _tileImageList.Count) - threshold += 5; - } - } - - // Apply found tile to section - //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); - //tileFound.ResizedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); - - this.ApplyTileFoundProcessor(x, y, tileFound.ResizedImage, outputImage); - - _progress++; - }); - } - - // Adjust hue - get the first (random) tile found and adjust its colours to suit the average - private void SearchAndReplaceAdjustHue(Image outputImage, Size tileSize) - { - Random r = new Random(); - List tileQueue = new List(); - //int maxQueueLength = Math.Min(1000, Math.Max(0, _tileImageList.Count - 50)); - - Parallel.For(0, _tX * _tY, xy => - { - int y = xy / _tX; - int x = xy % _tX; - - // (R * ColCount) + C - int index = ((y * _tX) + x) % _tileImageList.Count; - - // Check if it's the same as the last (X)? - //if (tileQueue.Count > 1) - //{ - // while (tileQueue.Contains(_tileImageList[index])) - // { - // index = r.Next(_tileImageList.Count); - // } - //} - - // Add to the 'queue' - Tile tileFound = _tileImageList[index]; - //if (tileQueue.Count >= maxQueueLength && tileQueue.Count > 0) - // tileQueue.RemoveAt(0); - //tileQueue.Add(tileFound); - - // Adjust the hue - Image adjustedImage = new Image(tileFound.ResizedImage.Width, tileFound.ResizedImage.Height); - - //var adjustHueProcessor = new AdjustHueProcessor(tileFound.ResizedImage, _avgsMaster[x, y]); - //adjustedImage.Mutate(c => c.ApplyProcessor(adjustHueProcessor)); - - AdjustHue(tileFound.ResizedImage, adjustedImage, _avgsMaster[x, y]); - - // Apply found tile to section - //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); - //adjustedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); - - this.ApplyTileFoundProcessor(x, y, adjustedImage, outputImage); - - _progress++; - }); - } - - private void AdjustHue(Image source, Image output, Rgba32 averageColor) - { - output.Mutate(c => - { - Parallel.For(0, source.Height, h => - { - var rowSpan = source.GetPixelRowSpan(h); - - for (int w = 0; w < source.Width; w++) - { - Rgba32 pixel = new Rgba32(); - rowSpan[w].ToRgba32(ref pixel); - - int R = Math.Min(255, Math.Max(0, (pixel.R + averageColor.R) / 2)); - int G = Math.Min(255, Math.Max(0, (pixel.G + averageColor.G) / 2)); - int B = Math.Min(255, Math.Max(0, (pixel.B + averageColor.B) / 2)); - - Color clAvg = new Rgba32(Convert.ToByte(R), Convert.ToByte(G), Convert.ToByte(B)); - - Rgba32 pixelColor = clAvg.ToPixel(); - output[w, h] = pixelColor; - } - }); - }); - } - - // Use just mosic colored tiles - private void PlainColor(Image outputImage, Size tileSize) - { - Parallel.For(0, _tX * _tY, xy => - { - int y = xy / _tX; - int x = xy % _tX; - - // Generate colored tile - Image adjustedImage = new Image(tileSize.Width, tileSize.Height); - //var plainColorProcessor = new PlainColorProcessor(_avgsMaster[x, y]); - //adjustedImage.Mutate(c => c.ApplyProcessor(plainColorProcessor)); - - Vector4 averageColor4 = _avgsMaster[x, y].ToVector4(); - - adjustedImage.Mutate(c => c.ProcessPixelRowsAsVector4(row => - { - foreach (ref Vector4 pixel in row) - { - pixel = (pixel + averageColor4) / 2; - } - })); - - // Apply found tile to section - //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); - //adjustedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); - - this.ApplyTileFoundProcessor(x, y, adjustedImage, outputImage); - - _progress++; - }); - } - - - private int GetDifference(Rgba32 source, Rgba32 target) - { - int dR = Math.Abs(source.R - target.R); - int dG = Math.Abs(source.G - target.G); - int dB = Math.Abs(source.B - target.B); - int diff = Math.Max(dR, dG); - return Math.Max(diff, dB); - } - - public void Reset() { _masterImage = null; diff --git a/Yugen.Mosaic.Uwp/Services/PlainColorSearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/PlainColorSearchAndReplaceService.cs new file mode 100644 index 0000000..2b2f088 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Services/PlainColorSearchAndReplaceService.cs @@ -0,0 +1,51 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using System.Collections.Generic; +using System.Numerics; +using System.Threading.Tasks; +using Yugen.Mosaic.Uwp.Models; +using Size = SixLabors.ImageSharp.Size; + +namespace Yugen.Mosaic.Uwp.Services +{ + public class PlainColorSearchAndReplaceService : SearchAndReplaceService + { + public PlainColorSearchAndReplaceService(Image outputImage, Size tileSize, int tX, int tY, List tileImageList, Rgba32[,] avgsMaster) : base(outputImage, tileSize, tX, tY, tileImageList, avgsMaster) + { + } + + // Use just mosic colored tiles + public override void SearchAndReplace() + { + Parallel.For(0, _tX * _tY, xy => + { + int y = xy / _tX; + int x = xy % _tX; + + // Generate colored tile + Image adjustedImage = new Image(_tileSize.Width, _tileSize.Height); + //var plainColorProcessor = new PlainColorProcessor(_avgsMaster[x, y]); + //adjustedImage.Mutate(c => c.ApplyProcessor(plainColorProcessor)); + + Vector4 averageColor4 = _avgsMaster[x, y].ToVector4(); + + adjustedImage.Mutate(c => c.ProcessPixelRowsAsVector4(row => + { + foreach (ref Vector4 pixel in row) + { + pixel = (pixel + averageColor4) / 2; + } + })); + + // Apply found tile to section + //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); + //adjustedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); + + this.ApplyTileFoundProcessor(x, y, adjustedImage); + + //_progress++; + }); + } + } +} diff --git a/Yugen.Mosaic.Uwp/Services/RandomSearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/RandomSearchAndReplaceService.cs new file mode 100644 index 0000000..346a5f1 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Services/RandomSearchAndReplaceService.cs @@ -0,0 +1,60 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Yugen.Mosaic.Uwp.Helpers; +using Yugen.Mosaic.Uwp.Models; +using Size = SixLabors.ImageSharp.Size; + +namespace Yugen.Mosaic.Uwp.Services +{ + public class RandomSearchAndReplaceService : SearchAndReplaceService + { + public RandomSearchAndReplaceService(Image outputImage, Size tileSize, int tX, int tY, List tileImageList, Rgba32[,] avgsMaster) : base(outputImage, tileSize, tX, tY, tileImageList, avgsMaster) + { + } + + // Don't adjust hue - keep searching for a tile close enough + public override void SearchAndReplace() + { + Random r = new Random(); + + Parallel.For(0, _tX * _tY, xy => + { + int y = xy / _tX; + int x = xy % _tX; + + // Reset searching variables + int threshold = 0; + int searchCounter = 0; + Tile tileFound = null; + + // Search for a tile with a similar color + while (tileFound == null) + { + int index = r.Next(_tileImageList.Count); + var difference = ColorHelper.GetDifference(_avgsMaster[x, y], _tileImageList[index].AverageColor); + if (difference < threshold) + { + tileFound = _tileImageList[index]; + } + else + { + searchCounter++; + if (searchCounter >= _tileImageList.Count) + threshold += 5; + } + } + + // Apply found tile to section + //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); + //tileFound.ResizedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); + + this.ApplyTileFoundProcessor(x, y, tileFound.ResizedImage); + + //_progress++; + }); + } + } +} diff --git a/Yugen.Mosaic.Uwp/Services/SearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/SearchAndReplaceService.cs new file mode 100644 index 0000000..1b35664 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Services/SearchAndReplaceService.cs @@ -0,0 +1,47 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using System; +using System.Collections.Generic; +using Yugen.Mosaic.Uwp.Interfaces; +using Yugen.Mosaic.Uwp.Models; +using Size = SixLabors.ImageSharp.Size; + +namespace Yugen.Mosaic.Uwp.Services +{ + public abstract class SearchAndReplaceService : ISearchAndReplaceService + { + internal readonly Image _outputImage; + internal readonly Size _tileSize; + internal readonly int _tX; + internal readonly int _tY; + internal readonly List _tileImageList; + internal readonly Rgba32[,] _avgsMaster; + + public SearchAndReplaceService(Image outputImage, Size tileSize, int tX, int tY, List tileImageList, Rgba32[,] avgsMaster) + { + _outputImage = outputImage; + _tileSize = tileSize; + _tX = tX; + _tY = tY; + _tileImageList = tileImageList; + _avgsMaster = avgsMaster; + } + + public virtual void SearchAndReplace() { } + + // TODO: check this out + internal void ApplyTileFoundProcessor(int x, int y, Image source) + { + _outputImage.Mutate(c => + { + var point = new Point(x * source.Width, y * source.Height); + try + { + c.DrawImage(source, point, 1); + } + catch { } + }); + } + } +} diff --git a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj index a5ebcab..5a1d3c2 100644 --- a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj +++ b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj @@ -152,7 +152,14 @@ + + + + + + + SettingsDialog.xaml From af912536446e9f41b4b8c7c8ab0cd1dc5bc2b8a1 Mon Sep 17 00:00:00 2001 From: Emiliano Magliocca Date: Tue, 5 May 2020 09:59:27 +0300 Subject: [PATCH 6/7] Fix ApplyTileFoundProcessor --- .../Services/SearchAndReplaceService.cs | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/Yugen.Mosaic.Uwp/Services/SearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/SearchAndReplaceService.cs index 1b35664..38e4819 100644 --- a/Yugen.Mosaic.Uwp/Services/SearchAndReplaceService.cs +++ b/Yugen.Mosaic.Uwp/Services/SearchAndReplaceService.cs @@ -1,11 +1,10 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using System; using System.Collections.Generic; +using System.Threading.Tasks; using Yugen.Mosaic.Uwp.Interfaces; using Yugen.Mosaic.Uwp.Models; -using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp.Services { @@ -30,17 +29,34 @@ public SearchAndReplaceService(Image outputImage, Size tileSize, int tX, public virtual void SearchAndReplace() { } - // TODO: check this out + // TODO: c.DrawImage crash (System.NullReferenceException) + // with the current SixLabors.ImageSharp.Drawing preview version + //internal void ApplyTileFoundProcessor(int x, int y, Image source) + //{ + // _outputImage.Mutate(c => + // { + // var point = new Point(x * source.Width, y * source.Height); + // try + // { + // c.DrawImage(source, point, 1); + // } + // catch { } + // }); + //} + internal void ApplyTileFoundProcessor(int x, int y, Image source) { - _outputImage.Mutate(c => + Parallel.For(0, source.Height, h => { - var point = new Point(x * source.Width, y * source.Height); - try + Span rowSpan = source.GetPixelRowSpan(h); + + for (var w = 0; w < source.Width; w++) { - c.DrawImage(source, point, 1); + var pixel = new Rgba32(); + rowSpan[w].ToRgba32(ref pixel); + + _outputImage[x * source.Width + w, y * source.Height + h] = pixel; } - catch { } }); } } From c7123e2eab6a274b34d5e5d606c095d1aef39cb3 Mon Sep 17 00:00:00 2001 From: Emiliano Magliocca Date: Tue, 5 May 2020 09:59:45 +0300 Subject: [PATCH 7/7] Cleanup --- Yugen.Mosaic.Uwp/App.xaml.cs | 13 +- Yugen.Mosaic.Uwp/Controls/AlignmentGrid.cs | 27 ++-- Yugen.Mosaic.Uwp/Extensions/SettingsHelper.cs | 14 +- Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs | 14 +- Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs | 7 +- Yugen.Mosaic.Uwp/Helpers/RatioHelper.cs | 2 +- Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs | 5 +- Yugen.Mosaic.Uwp/Interfaces/IMosaicService.cs | 18 +++ Yugen.Mosaic.Uwp/MainPage.xaml.cs | 4 +- .../Processors/AdjustHueProcessor.cs | 2 +- .../Processors/ApplyTileFoundProcessor.cs | 2 +- .../Processors/GetTileAverageProcessor.cs | 2 +- .../Processors/GetTilesAverageProcessor.cs | 1 - Yugen.Mosaic.Uwp/Properties/AssemblyInfo.cs | 1 - .../AdjustHueSearchAndReplaceService.cs | 15 +- .../ClassicSearchAndReplaceService.cs | 1 - Yugen.Mosaic.Uwp/Services/MosaicService.cs | 21 +-- .../PlainColorSearchAndReplaceService.cs | 7 +- .../Services/RandomSearchAndReplaceService.cs | 17 +- .../Services/ThemeSelectorService.cs | 18 +-- Yugen.Mosaic.Uwp/SettingsDialog.xaml.cs | 7 +- Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs | 145 ++++++++---------- .../ViewModels/SettingsViewModel.cs | 6 +- Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj | 3 +- 24 files changed, 163 insertions(+), 189 deletions(-) create mode 100644 Yugen.Mosaic.Uwp/Interfaces/IMosaicService.cs diff --git a/Yugen.Mosaic.Uwp/App.xaml.cs b/Yugen.Mosaic.Uwp/App.xaml.cs index af2d86b..8a4ace6 100644 --- a/Yugen.Mosaic.Uwp/App.xaml.cs +++ b/Yugen.Mosaic.Uwp/App.xaml.cs @@ -15,7 +15,7 @@ namespace Yugen.Mosaic.Uwp /// /// Provides application-specific behavior to supplement the default Application class. /// - sealed partial class App : Application + public sealed partial class App : Application { /// /// Initializes the singleton application object. This is the first line of authored code @@ -23,8 +23,8 @@ sealed partial class App : Application /// public App() { - this.InitializeComponent(); - this.Suspending += OnSuspending; + InitializeComponent(); + Suspending += OnSuspending; AppCenter.Start("7df4b441-69ae-49c5-b27d-5a532f33b554", typeof(Analytics), typeof(Crashes)); @@ -76,10 +76,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e) /// /// The Frame which failed navigation /// Details about the navigation failure - void OnNavigationFailed(object sender, NavigationFailedEventArgs e) - { - throw new Exception("Failed to load Page " + e.SourcePageType.FullName); - } + private void OnNavigationFailed(object sender, NavigationFailedEventArgs e) => throw new Exception("Failed to load Page " + e.SourcePageType.FullName); /// /// Invoked when application execution is being suspended. Application state is saved @@ -90,7 +87,7 @@ void OnNavigationFailed(object sender, NavigationFailedEventArgs e) /// Details about the suspend request. private void OnSuspending(object sender, SuspendingEventArgs e) { - var deferral = e.SuspendingOperation.GetDeferral(); + SuspendingDeferral deferral = e.SuspendingOperation.GetDeferral(); //TODO: Save application state and stop any background activity deferral.Complete(); } diff --git a/Yugen.Mosaic.Uwp/Controls/AlignmentGrid.cs b/Yugen.Mosaic.Uwp/Controls/AlignmentGrid.cs index 563fc4f..b71f013 100644 --- a/Yugen.Mosaic.Uwp/Controls/AlignmentGrid.cs +++ b/Yugen.Mosaic.Uwp/Controls/AlignmentGrid.cs @@ -60,8 +60,8 @@ private static void OnPropertyChanged(DependencyObject dependencyObject, Depende /// public Brush LineBrush { - get { return (Brush)GetValue(LineBrushProperty); } - set { SetValue(LineBrushProperty, value); } + get => (Brush)GetValue(LineBrushProperty); + set => SetValue(LineBrushProperty, value); } /// @@ -69,8 +69,8 @@ public Brush LineBrush /// public double HorizontalStep { - get { return (double)GetValue(HorizontalStepProperty); } - set { SetValue(HorizontalStepProperty, value); } + get => (double)GetValue(HorizontalStepProperty); + set => SetValue(HorizontalStepProperty, value); } /// @@ -78,8 +78,8 @@ public double HorizontalStep /// public double VerticalStep { - get { return (double)GetValue(VerticalStepProperty); } - set { SetValue(VerticalStepProperty, value); } + get => (double)GetValue(VerticalStepProperty); + set => SetValue(VerticalStepProperty, value); } /// @@ -87,8 +87,8 @@ public double VerticalStep /// public double ContainerWidth { - get { return (double)GetValue(ContainerWidthProperty); } - set { SetValue(ContainerWidthProperty, value); } + get => (double)GetValue(ContainerWidthProperty); + set => SetValue(ContainerWidthProperty, value); } /// @@ -96,8 +96,8 @@ public double ContainerWidth /// public double ContainerHeight { - get { return (double)GetValue(ContainerHeightProperty); } - set { SetValue(ContainerHeightProperty, value); } + get => (double)GetValue(ContainerHeightProperty); + set => SetValue(ContainerHeightProperty, value); } /// @@ -121,7 +121,7 @@ private void Rebuild() containerCanvas.Children.Clear(); var horizontalStep = HorizontalStep; var verticalStep = VerticalStep; - var brush = LineBrush ?? (Brush)Application.Current.Resources["ApplicationForegroundThemeBrush"]; + Brush brush = LineBrush ?? (Brush)Application.Current.Resources["ApplicationForegroundThemeBrush"]; if (horizontalStep > 0) { @@ -156,9 +156,6 @@ private void Rebuild() } } - private void AlignmentGrid_SizeChanged(object sender, SizeChangedEventArgs e) - { - Rebuild(); - } + private void AlignmentGrid_SizeChanged(object sender, SizeChangedEventArgs e) => Rebuild(); } } \ No newline at end of file diff --git a/Yugen.Mosaic.Uwp/Extensions/SettingsHelper.cs b/Yugen.Mosaic.Uwp/Extensions/SettingsHelper.cs index 8e617bb..e0f8512 100644 --- a/Yugen.Mosaic.Uwp/Extensions/SettingsHelper.cs +++ b/Yugen.Mosaic.Uwp/Extensions/SettingsHelper.cs @@ -21,18 +21,12 @@ public static void Write(string key, T value) LocalSettings.Values[key] = valueString; } - public static async Task ReadAsync(string key) - { - return LocalSettings.Values.TryGetValue(key, out object value) - ? await JsonProvider.ToObjectAsync((string) value) + public static async Task ReadAsync(string key) => LocalSettings.Values.TryGetValue(key, out var value) + ? await JsonProvider.ToObjectAsync((string)value) : default; - } - public static T Read(string key) - { - return LocalSettings.Values.TryGetValue(key, out object value) - ? JsonConvert.DeserializeObject((string) value) + public static T Read(string key) => LocalSettings.Values.TryGetValue(key, out var value) + ? JsonConvert.DeserializeObject((string)value) : default; - } } } \ No newline at end of file diff --git a/Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs b/Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs index ead3595..a74a028 100644 --- a/Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs +++ b/Yugen.Mosaic.Uwp/Helpers/ColorHelper.cs @@ -20,11 +20,11 @@ private static Rgba32 GetAverageColor(Image source, int startX, int star Parallel.For(startY, endY, h => { - var rowSpan = source.GetPixelRowSpan(h); + Span rowSpan = source.GetPixelRowSpan(h); - for (int w = startX; w < endX; w++) + for (var w = startX; w < endX; w++) { - Rgba32 pixel = new Rgba32(); + var pixel = new Rgba32(); rowSpan[w].ToRgba32(ref pixel); aR += pixel.R; @@ -43,10 +43,10 @@ private static Rgba32 GetAverageColor(Image source, int startX, int star public static int GetDifference(Rgba32 source, Rgba32 target) { - int dR = Math.Abs(source.R - target.R); - int dG = Math.Abs(source.G - target.G); - int dB = Math.Abs(source.B - target.B); - int diff = Math.Max(dR, dG); + var dR = Math.Abs(source.R - target.R); + var dG = Math.Abs(source.G - target.G); + var dB = Math.Abs(source.B - target.B); + var diff = Math.Max(dR, dG); return Math.Max(diff, dB); } } diff --git a/Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs b/Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs index dcfc7dc..899cc91 100644 --- a/Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs +++ b/Yugen.Mosaic.Uwp/Helpers/OnboardingHelper.cs @@ -18,9 +18,7 @@ public static bool IsDisabled private static int _step; private static OnboardingElement[] _onboardingElements; - public static void Init(FrameworkElement[] frameworkElements) - { - _onboardingElements = new OnboardingElement[] + public static void Init(FrameworkElement[] frameworkElements) => _onboardingElements = new OnboardingElement[] { new OnboardingElement( frameworkElements[0], @@ -44,14 +42,15 @@ public static void Init(FrameworkElement[] frameworkElements) frameworkElements[6], OnboardingStage.Save), }; - } public static OnboardingElement ShowTeachingTip() { OnboardingElement onboardingElement = null; if (_step < 0 || IsDisabled) + { return onboardingElement; + } if (_step < _onboardingElements.Length) { diff --git a/Yugen.Mosaic.Uwp/Helpers/RatioHelper.cs b/Yugen.Mosaic.Uwp/Helpers/RatioHelper.cs index 077d185..5f3e4c6 100644 --- a/Yugen.Mosaic.Uwp/Helpers/RatioHelper.cs +++ b/Yugen.Mosaic.Uwp/Helpers/RatioHelper.cs @@ -7,7 +7,7 @@ public static class RatioHelper public static Tuple Convert(int width, int height, int newHeight, int newWidth) { //calculate the ratio - double ratio = (double)width / (double)height; + var ratio = (double)width / (double)height; //set height of image to boxHeight and check if resulting width is less than boxWidth, //else set width of image to boxWidth and calculate new height diff --git a/Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs b/Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs index 5a1301b..cda2e33 100644 --- a/Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs +++ b/Yugen.Mosaic.Uwp/Helpers/ResourceHelper.cs @@ -6,9 +6,6 @@ public static class ResourceHelper { private static readonly ResourceLoader _resourceLoader = _resourceLoader ?? new ResourceLoader(); - public static string GetText(string key) - { - return _resourceLoader.GetString(key); - } + public static string GetText(string key) => _resourceLoader.GetString(key); } } \ No newline at end of file diff --git a/Yugen.Mosaic.Uwp/Interfaces/IMosaicService.cs b/Yugen.Mosaic.Uwp/Interfaces/IMosaicService.cs new file mode 100644 index 0000000..deed307 --- /dev/null +++ b/Yugen.Mosaic.Uwp/Interfaces/IMosaicService.cs @@ -0,0 +1,18 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using System.IO; +using Windows.Storage.Streams; + +namespace Yugen.Mosaic.Uwp.Interfaces +{ + public interface IMosaicService + { + Image AddMasterImage(Stream stream); + Image AddTileImage(string name, Stream stream); + Image GenerateMosaic(Size outputSize, Size tileSize, int mosaicType); + Image GetResizedImage(Image image, int size); + InMemoryRandomAccessStream GetStream(Image image); + void RemoveTileImage(string name); + void Reset(); + } +} \ No newline at end of file diff --git a/Yugen.Mosaic.Uwp/MainPage.xaml.cs b/Yugen.Mosaic.Uwp/MainPage.xaml.cs index 2a2009f..e01836b 100644 --- a/Yugen.Mosaic.Uwp/MainPage.xaml.cs +++ b/Yugen.Mosaic.Uwp/MainPage.xaml.cs @@ -14,13 +14,13 @@ public sealed partial class MainPage : Page public MainPage() { - this.InitializeComponent(); + InitializeComponent(); ExtendToTitleBar(); } private void ExtendToTitleBar() { - var coreTitleBar = CoreApplication.GetCurrentView().TitleBar; + CoreApplicationViewTitleBar coreTitleBar = CoreApplication.GetCurrentView().TitleBar; coreTitleBar.ExtendViewIntoTitleBar = true; } diff --git a/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs b/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs index 021d07d..6d65089 100644 --- a/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/AdjustHueProcessor.cs @@ -67,7 +67,7 @@ // int B = Math.Min(255, Math.Max(0, (pixel.B + _averageColor.B) / 2)); // Color clAvg = new Rgba32(Convert.ToByte(R), Convert.ToByte(G), Convert.ToByte(B)); - + // TPixel pixelColor = clAvg.ToPixel(); // _source[w, h] = pixelColor; // } diff --git a/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs b/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs index 0dbabe8..a4a0c76 100644 --- a/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/ApplyTileFoundProcessor.cs @@ -63,7 +63,7 @@ // _outputImage = definition.OutputImage; // } - + // /// // public void Execute() // { diff --git a/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs b/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs index 9a73c4a..d2aa0aa 100644 --- a/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/GetTileAverageProcessor.cs @@ -67,7 +67,7 @@ // _resizedImage = definition.ResizedImage; // _averageColor = definition.AverageColor; // } - + // /// // public void Execute() // { diff --git a/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs b/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs index afed0ce..ad32b4c 100644 --- a/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs +++ b/Yugen.Mosaic.Uwp/Processors/GetTilesAverageProcessor.cs @@ -4,7 +4,6 @@ //using System; //using System.Threading.Tasks; //using Rectangle = SixLabors.ImageSharp.Rectangle; -//using Size = SixLabors.ImageSharp.Size; //namespace Yugen.Mosaic.Uwp.Processors //{ diff --git a/Yugen.Mosaic.Uwp/Properties/AssemblyInfo.cs b/Yugen.Mosaic.Uwp/Properties/AssemblyInfo.cs index 9a1479d..d53b0dd 100644 --- a/Yugen.Mosaic.Uwp/Properties/AssemblyInfo.cs +++ b/Yugen.Mosaic.Uwp/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/Yugen.Mosaic.Uwp/Services/AdjustHueSearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/AdjustHueSearchAndReplaceService.cs index d2c8154..37e36b7 100644 --- a/Yugen.Mosaic.Uwp/Services/AdjustHueSearchAndReplaceService.cs +++ b/Yugen.Mosaic.Uwp/Services/AdjustHueSearchAndReplaceService.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using Yugen.Mosaic.Uwp.Models; -using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp.Services { @@ -18,17 +17,17 @@ public AdjustHueSearchAndReplaceService(Image outputImage, Size tileSize // Adjust hue - get the first (random) tile found and adjust its colours to suit the average public override void SearchAndReplace() { - Random r = new Random(); - List tileQueue = new List(); + var r = new Random(); + var tileQueue = new List(); //int maxQueueLength = Math.Min(1000, Math.Max(0, _tileImageList.Count - 50)); Parallel.For(0, _tX * _tY, xy => { - int y = xy / _tX; - int x = xy % _tX; + var y = xy / _tX; + var x = xy % _tX; // (R * ColCount) + C - int index = ((y * _tX) + x) % _tileImageList.Count; + var index = ((y * _tX) + x) % _tileImageList.Count; // Check if it's the same as the last (X)? //if (tileQueue.Count > 1) @@ -46,7 +45,7 @@ public override void SearchAndReplace() //tileQueue.Add(tileFound); // Adjust the hue - Image adjustedImage = new Image(tileFound.ResizedImage.Width, tileFound.ResizedImage.Height); + var adjustedImage = new Image(tileFound.ResizedImage.Width, tileFound.ResizedImage.Height); //var adjustHueProcessor = new AdjustHueProcessor(tileFound.ResizedImage, _avgsMaster[x, y]); //adjustedImage.Mutate(c => c.ApplyProcessor(adjustHueProcessor)); @@ -57,7 +56,7 @@ public override void SearchAndReplace() //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); //adjustedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); - this.ApplyTileFoundProcessor(x, y, adjustedImage); + ApplyTileFoundProcessor(x, y, adjustedImage); //_progress++; }); diff --git a/Yugen.Mosaic.Uwp/Services/ClassicSearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/ClassicSearchAndReplaceService.cs index d0a88ed..e032885 100644 --- a/Yugen.Mosaic.Uwp/Services/ClassicSearchAndReplaceService.cs +++ b/Yugen.Mosaic.Uwp/Services/ClassicSearchAndReplaceService.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Yugen.Mosaic.Uwp.Helpers; using Yugen.Mosaic.Uwp.Models; -using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp.Services { diff --git a/Yugen.Mosaic.Uwp/Services/MosaicService.cs b/Yugen.Mosaic.Uwp/Services/MosaicService.cs index a5ad72d..3333fab 100644 --- a/Yugen.Mosaic.Uwp/Services/MosaicService.cs +++ b/Yugen.Mosaic.Uwp/Services/MosaicService.cs @@ -11,11 +11,10 @@ using Yugen.Mosaic.Uwp.Helpers; using Yugen.Mosaic.Uwp.Interfaces; using Yugen.Mosaic.Uwp.Models; -using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp.Services { - public class MosaicService + public class MosaicService : IMosaicService { private Image _masterImage; @@ -45,9 +44,11 @@ public Image AddTileImage(string name, Stream stream) public void RemoveTileImage(string name) { - var item = _tileImageList.FirstOrDefault(x => x.Name.Equals(name)); + Tile item = _tileImageList.FirstOrDefault(x => x.Name.Equals(name)); if (item != null) + { _tileImageList.Remove(item); + } } public Image GetResizedImage(Image image, int size) @@ -63,7 +64,7 @@ public Image GetResizedImage(Image image, int size) public InMemoryRandomAccessStream GetStream(Image image) { - InMemoryRandomAccessStream outputStream = new InMemoryRandomAccessStream(); + var outputStream = new InMemoryRandomAccessStream(); image.SaveAsJpeg(outputStream.AsStreamForWrite()); outputStream.Seek(0); return outputStream; @@ -73,7 +74,9 @@ public InMemoryRandomAccessStream GetStream(Image image) public Image GenerateMosaic(Size outputSize, Size tileSize, int mosaicType) { if (_masterImage == null || (mosaicType != 2 && _tileImageList.Count < 1)) + { return null; + } Image resizedMasterImage = _masterImage.Clone(x => x.Resize(outputSize.Width, outputSize.Height)); @@ -92,28 +95,26 @@ public Image GenerateMosaic(Size outputSize, Size tileSize, int mosaicTy } - private void GetTilesAverage(Image masterImage) - { + private void GetTilesAverage(Image masterImage) => //var getTilesAverageProcessor = new GetTilesAverageProcessor(_tX, _tY, _tileSize, _avgsMaster); //masterImage.Mutate(c => c.ApplyProcessor(getTilesAverageProcessor)); Parallel.For(0, _tY, y => { - var rowSpan = masterImage.GetPixelRowSpan(y); + Span rowSpan = masterImage.GetPixelRowSpan(y); - for (int x = 0; x < _tX; x++) + for (var x = 0; x < _tX; x++) { _avgsMaster[x, y].FromRgba32(ColorHelper.GetAverageColor(masterImage, x, y, _tileSize)); } }); - } private void LoadTilesAndResize() { _progressMax = _tileImageList.Count; _progress = 0; - foreach (var tile in _tileImageList) + foreach (Tile tile in _tileImageList) { //var getTileAverageProcessor = new GetTileAverageProcessor(0, 0, _tileSize.Width, _tileSize.Height, tile.OriginalImage); //tile.OriginalImage.Mutate(c => c.ApplyProcessor(getTileAverageProcessor)); diff --git a/Yugen.Mosaic.Uwp/Services/PlainColorSearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/PlainColorSearchAndReplaceService.cs index 2b2f088..359093b 100644 --- a/Yugen.Mosaic.Uwp/Services/PlainColorSearchAndReplaceService.cs +++ b/Yugen.Mosaic.Uwp/Services/PlainColorSearchAndReplaceService.cs @@ -5,7 +5,6 @@ using System.Numerics; using System.Threading.Tasks; using Yugen.Mosaic.Uwp.Models; -using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp.Services { @@ -24,11 +23,11 @@ public override void SearchAndReplace() int x = xy % _tX; // Generate colored tile - Image adjustedImage = new Image(_tileSize.Width, _tileSize.Height); + var adjustedImage = new Image(_tileSize.Width, _tileSize.Height); //var plainColorProcessor = new PlainColorProcessor(_avgsMaster[x, y]); //adjustedImage.Mutate(c => c.ApplyProcessor(plainColorProcessor)); - Vector4 averageColor4 = _avgsMaster[x, y].ToVector4(); + var averageColor4 = _avgsMaster[x, y].ToVector4(); adjustedImage.Mutate(c => c.ProcessPixelRowsAsVector4(row => { @@ -42,7 +41,7 @@ public override void SearchAndReplace() //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); //adjustedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); - this.ApplyTileFoundProcessor(x, y, adjustedImage); + ApplyTileFoundProcessor(x, y, adjustedImage); //_progress++; }); diff --git a/Yugen.Mosaic.Uwp/Services/RandomSearchAndReplaceService.cs b/Yugen.Mosaic.Uwp/Services/RandomSearchAndReplaceService.cs index 346a5f1..69aaf99 100644 --- a/Yugen.Mosaic.Uwp/Services/RandomSearchAndReplaceService.cs +++ b/Yugen.Mosaic.Uwp/Services/RandomSearchAndReplaceService.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using Yugen.Mosaic.Uwp.Helpers; using Yugen.Mosaic.Uwp.Models; -using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp.Services { @@ -18,22 +17,22 @@ public RandomSearchAndReplaceService(Image outputImage, Size tileSize, i // Don't adjust hue - keep searching for a tile close enough public override void SearchAndReplace() { - Random r = new Random(); + var r = new Random(); Parallel.For(0, _tX * _tY, xy => { - int y = xy / _tX; - int x = xy % _tX; + var y = xy / _tX; + var x = xy % _tX; // Reset searching variables - int threshold = 0; - int searchCounter = 0; + var threshold = 0; + var searchCounter = 0; Tile tileFound = null; // Search for a tile with a similar color while (tileFound == null) { - int index = r.Next(_tileImageList.Count); + var index = r.Next(_tileImageList.Count); var difference = ColorHelper.GetDifference(_avgsMaster[x, y], _tileImageList[index].AverageColor); if (difference < threshold) { @@ -43,7 +42,9 @@ public override void SearchAndReplace() { searchCounter++; if (searchCounter >= _tileImageList.Count) + { threshold += 5; + } } } @@ -51,7 +52,7 @@ public override void SearchAndReplace() //var applyTileFoundProcessor = new ApplyTileFoundProcessor(x, y, tileSize.Width, tileSize.Height, outputImage); //tileFound.ResizedImage.Mutate(c => c.ApplyProcessor(applyTileFoundProcessor)); - this.ApplyTileFoundProcessor(x, y, tileFound.ResizedImage); + ApplyTileFoundProcessor(x, y, tileFound.ResizedImage); //_progress++; }); diff --git a/Yugen.Mosaic.Uwp/Services/ThemeSelectorService.cs b/Yugen.Mosaic.Uwp/Services/ThemeSelectorService.cs index e7caee3..f9363b4 100644 --- a/Yugen.Mosaic.Uwp/Services/ThemeSelectorService.cs +++ b/Yugen.Mosaic.Uwp/Services/ThemeSelectorService.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Windows.ApplicationModel.Core; -using Windows.Storage; using Windows.UI; using Windows.UI.Core; using Windows.UI.ViewManagement; @@ -20,7 +19,7 @@ public static class ThemeSelectorService public static async Task InitializeAsync() { - var theme = await LoadThemeFromSettingsAsync(); + ElementTheme theme = await LoadThemeFromSettingsAsync(); await SetThemeAsync(theme); } @@ -31,7 +30,7 @@ public static async Task SetThemeAsync(ElementTheme theme) await SetRequestedThemeAsync(); await SaveThemeInSettingsAsync(Theme); - var titleBar = ApplicationView.GetForCurrentView().TitleBar; + ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar; //Active titleBar.BackgroundColor = Colors.Transparent; @@ -48,7 +47,7 @@ public static async Task SetThemeAsync(ElementTheme theme) public static async Task SetRequestedThemeAsync() { - foreach (var view in CoreApplication.Views) + foreach (CoreApplicationView view in CoreApplication.Views) { await view.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { @@ -63,7 +62,7 @@ await view.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => private static async Task LoadThemeFromSettingsAsync() { ElementTheme cacheTheme = ElementTheme.Default; - string themeName = await SettingsHelper.ReadAsync(SettingsKey); + var themeName = await SettingsHelper.ReadAsync(SettingsKey); if (!string.IsNullOrEmpty(themeName)) { @@ -73,17 +72,14 @@ private static async Task LoadThemeFromSettingsAsync() return cacheTheme; } - private static async Task SaveThemeInSettingsAsync(ElementTheme theme) - { - await SettingsHelper.WriteAsync(SettingsKey, theme.ToString()); - } + private static async Task SaveThemeInSettingsAsync(ElementTheme theme) => await SettingsHelper.WriteAsync(SettingsKey, theme.ToString()); private static T GetThemeResource(ElementTheme theme, string resKey) { - bool isLightTheme = (theme == ElementTheme.Default) + var isLightTheme = (theme == ElementTheme.Default) ? (IsSystemThemeLight()) : (theme == ElementTheme.Light); - string themeKey = isLightTheme ? "Light" : "Dark"; + var themeKey = isLightTheme ? "Light" : "Dark"; var themeDictionary = (ResourceDictionary)Application.Current.Resources.ThemeDictionaries[themeKey]; return (T)themeDictionary[resKey]; } diff --git a/Yugen.Mosaic.Uwp/SettingsDialog.xaml.cs b/Yugen.Mosaic.Uwp/SettingsDialog.xaml.cs index 53771c2..21515c4 100644 --- a/Yugen.Mosaic.Uwp/SettingsDialog.xaml.cs +++ b/Yugen.Mosaic.Uwp/SettingsDialog.xaml.cs @@ -9,12 +9,9 @@ public sealed partial class SettingsDialog : ContentDialog { public SettingsDialog() { - this.InitializeComponent(); + InitializeComponent(); } - private void Button_Tapped(object sender, TappedRoutedEventArgs e) - { - Hide(); - } + private void Button_Tapped(object sender, TappedRoutedEventArgs e) => Hide(); } } diff --git a/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs b/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs index 0a3ecff..2ffe53b 100644 --- a/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs +++ b/Yugen.Mosaic.Uwp/ViewModels/MainViewModel.cs @@ -21,7 +21,6 @@ using Yugen.Mosaic.Uwp.Services; using Yugen.Toolkit.Uwp.Helpers; using Yugen.Toolkit.Uwp.ViewModels; -using Size = SixLabors.ImageSharp.Size; namespace Yugen.Mosaic.Uwp { @@ -31,16 +30,16 @@ public class MainViewModel : BaseViewModel public BitmapImage MasterBpmSource { - get { return _masterBmpSource; } - set { Set(ref _masterBmpSource, value); } + get => _masterBmpSource; + set => Set(ref _masterBmpSource, value); } private bool _isAddMasterUIVisible = true; public bool IsAddMasterUIVisible { - get { return _isAddMasterUIVisible; } - set { Set(ref _isAddMasterUIVisible, value); } + get => _isAddMasterUIVisible; + set => Set(ref _isAddMasterUIVisible, value); } @@ -48,16 +47,16 @@ public bool IsAddMasterUIVisible public int TileWidth { - get { return _tileWidth; } - set { Set(ref _tileWidth, value); } + get => _tileWidth; + set => Set(ref _tileWidth, value); } private int _tileHeight = 25; public int TileHeight { - get { return _tileHeight; } - set { Set(ref _tileHeight, value); } + get => _tileHeight; + set => Set(ref _tileHeight, value); } private Size TileSize => new Size(_tileWidth, _tileHeight); @@ -66,8 +65,8 @@ public int TileHeight public ObservableCollection TileBmpCollection { - get { return _tileBmpCollection; } - set { Set(ref _tileBmpCollection, value); } + get => _tileBmpCollection; + set => Set(ref _tileBmpCollection, value); } @@ -75,24 +74,24 @@ public ObservableCollection TileBmpCollection public BitmapImage OutputBmpSource { - get { return _outputBmpSource; } - set { Set(ref _outputBmpSource, value); } + get => _outputBmpSource; + set => Set(ref _outputBmpSource, value); } private int _outputWidth = 1000; public int OutputWidth { - get { return _outputWidth; } - set { Set(ref _outputWidth, value); } + get => _outputWidth; + set => Set(ref _outputWidth, value); } private int _outputHeight = 1000; public int OutputHeight { - get { return _outputHeight; } - set { Set(ref _outputHeight, value); } + get => _outputHeight; + set => Set(ref _outputHeight, value); } private Size OutputSize => new Size(_outputWidth, _outputHeight); @@ -102,8 +101,8 @@ public int OutputHeight public bool IsAlignmentGridVisibile { - get { return _isAlignmentGridVisibile; } - set { Set(ref _isAlignmentGridVisibile, value); } + get => _isAlignmentGridVisibile; + set => Set(ref _isAlignmentGridVisibile, value); } @@ -119,8 +118,8 @@ public bool IsAlignmentGridVisibile public MosaicType SelectedMosaicType { - get { return _selectedMosaicType; } - set { Set(ref _selectedMosaicType, value); } + get => _selectedMosaicType; + set => Set(ref _selectedMosaicType, value); } @@ -128,8 +127,8 @@ public MosaicType SelectedMosaicType public bool IsLoading { - get { return _isLoading; } - set { Set(ref _isLoading, value); } + get => _isLoading; + set => Set(ref _isLoading, value); } private readonly MosaicService _mosaicService = new MosaicService(); @@ -141,32 +140,32 @@ public bool IsLoading public bool IsTeachingTipOpen { - get { return _isTeachingTipOpen; } - set { Set(ref _isTeachingTipOpen, value); } + get => _isTeachingTipOpen; + set => Set(ref _isTeachingTipOpen, value); } private string _teachingTipTitle; public string TeachingTipTitle { - get { return _teachingTipTitle; } - set { Set(ref _teachingTipTitle, value); } + get => _teachingTipTitle; + set => Set(ref _teachingTipTitle, value); } private string _teachingTipSubTitle; public string TeachingTipSubTitle { - get { return _teachingTipSubTitle; } - set { Set(ref _teachingTipSubTitle, value); } + get => _teachingTipSubTitle; + set => Set(ref _teachingTipSubTitle, value); } private FrameworkElement _teachingTipTarget; public FrameworkElement TeachingTipTarget { - get { return _teachingTipTarget; } - set { Set(ref _teachingTipTarget, value); } + get => _teachingTipTarget; + set => Set(ref _teachingTipTarget, value); } @@ -176,47 +175,28 @@ public MainViewModel() } - public void Grid_PointerEntered(object sender, PointerRoutedEventArgs e) - { - IsAddMasterUIVisible = true; - } + public void Grid_PointerEntered(object sender, PointerRoutedEventArgs e) => IsAddMasterUIVisible = true; - public void Grid_PointerExited(object sender, PointerRoutedEventArgs e) - { - UpdateIsAddMasterUIVisible(); - } + public void Grid_PointerExited(object sender, PointerRoutedEventArgs e) => UpdateIsAddMasterUIVisible(); - private void UpdateIsAddMasterUIVisible() - { - IsAddMasterUIVisible = (MasterBpmSource.PixelWidth > 0 && MasterBpmSource.PixelHeight > 0) ? false : true; - } + private void UpdateIsAddMasterUIVisible() => IsAddMasterUIVisible = (MasterBpmSource.PixelWidth > 0 && MasterBpmSource.PixelHeight > 0) ? false : true; - public void AddMasterGrid_Tapped(object sender, TappedRoutedEventArgs e) - { - AddMaster().FireAndForgetSafeAsync(); - } + public void AddMasterGrid_Tapped(object sender, TappedRoutedEventArgs e) => AddMaster().FireAndForgetSafeAsync(); - public void AddTilesButton_Click(object sender, RoutedEventArgs e) - { - AddTiles((Button) sender).FireAndForgetSafeAsync(); - } + public void AddTilesButton_Click(object sender, RoutedEventArgs e) => AddTiles((Button)sender).FireAndForgetSafeAsync(); public void AdaptiveGridView_ItemClick(object sender, ItemClickEventArgs e) { if (e.ClickedItem is TileBmp item) + { RemoveTile(item).FireAndForgetSafeAsync(); + } } - public void GenerateButton_Click(object sender, RoutedEventArgs e) - { - Generate((Button) sender).FireAndForgetSafeAsync(); - } + public void GenerateButton_Click(object sender, RoutedEventArgs e) => Generate((Button)sender).FireAndForgetSafeAsync(); - public void SaveButton_Click(object sender, RoutedEventArgs e) - { - Save((Button) sender).FireAndForgetSafeAsync(); - } + public void SaveButton_Click(object sender, RoutedEventArgs e) => Save((Button)sender).FireAndForgetSafeAsync(); public void ResetButton_Click(object sender, RoutedEventArgs e) { @@ -236,26 +216,23 @@ public void HelpButton_Click(object sender, RoutedEventArgs e) ShowTeachingTip(); } - public void SettingsButton_Click(object sender, RoutedEventArgs e) - { - Settings().FireAndForgetSafeAsync(); - } + public void SettingsButton_Click(object sender, RoutedEventArgs e) => Settings().FireAndForgetSafeAsync(); private async Task AddMaster() { IsLoading = true; - var masterFile = await FilePickerHelper.OpenFile( - new List {".jpg", ".png"}, + StorageFile masterFile = await FilePickerHelper.OpenFile( + new List { ".jpg", ".png" }, Windows.Storage.Pickers.PickerLocationId.PicturesLibrary); if (masterFile != null) { - using (var inputStream = await masterFile.OpenReadAsync()) - using (var stream = inputStream.AsStreamForRead()) + using (IRandomAccessStreamWithContentType inputStream = await masterFile.OpenReadAsync()) + using (Stream stream = inputStream.AsStreamForRead()) { - var image = _mosaicService.AddMasterImage(stream); + Image image = _mosaicService.AddMasterImage(stream); using (Image copy = _mosaicService.GetResizedImage(image, 400)) { @@ -263,7 +240,7 @@ private async Task AddMaster() await MasterBpmSource.SetSourceAsync(outputStream); } - var newSize = RatioHelper.Convert(image.Width, image.Height, OutputSize.Width, OutputSize.Height); + Tuple newSize = RatioHelper.Convert(image.Width, image.Height, OutputSize.Width, OutputSize.Height); OutputWidth = newSize.Item1; OutputHeight = newSize.Item2; } @@ -276,11 +253,13 @@ private async Task AddMaster() private async Task AddTiles(Button button) { - var files = await FilePickerHelper.OpenFiles( - new List {".jpg", ".png"}, + IReadOnlyList files = await FilePickerHelper.OpenFiles( + new List { ".jpg", ".png" }, Windows.Storage.Pickers.PickerLocationId.PicturesLibrary); if (files == null) + { return; + } button.IsEnabled = false; IsLoading = true; @@ -288,10 +267,10 @@ private async Task AddTiles(Button button) await Task.Run(() => Parallel.ForEach(files, async file => { - using (var inputStream = await file.OpenReadAsync()) - using (var stream = inputStream.AsStreamForRead()) + using (IRandomAccessStreamWithContentType inputStream = await file.OpenReadAsync()) + using (Stream stream = inputStream.AsStreamForRead()) { - var image = _mosaicService.AddTileImage(file.DisplayName, stream); + Image image = _mosaicService.AddTileImage(file.DisplayName, stream); using (Image copy = _mosaicService.GetResizedImage(image, 200)) { @@ -355,13 +334,15 @@ private async Task Save(Button button) {FileFormat.Jpg.ToString(), new List() {FileFormat.Jpg.FileFormatToString()}} }; - var file = await FilePickerHelper.SaveFile("Mosaic", fileTypes, + StorageFile file = await FilePickerHelper.SaveFile("Mosaic", fileTypes, Windows.Storage.Pickers.PickerLocationId.PicturesLibrary); if (file == null || _outputImage == null) + { return; + } - using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite)) + using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite)) { switch (file.FileType) { @@ -387,8 +368,11 @@ private async Task Settings() public void ShowTeachingTip() { - var onboardingElement = OnboardingHelper.ShowTeachingTip(); - if (onboardingElement == null) return; + OnboardingElement onboardingElement = OnboardingHelper.ShowTeachingTip(); + if (onboardingElement == null) + { + return; + } TeachingTipTitle = onboardingElement.Title; TeachingTipSubTitle = onboardingElement.Subtitle; @@ -404,10 +388,7 @@ public void TeachingTip_Closing(TeachingTip sender, TeachingTipClosingEventArgs IsTeachingTipOpen = false; } - public void TeachingTip_Closed(TeachingTip sender, TeachingTipClosedEventArgs args) - { - ShowTeachingTip(); - } + public void TeachingTip_Closed(TeachingTip sender, TeachingTipClosedEventArgs args) => ShowTeachingTip(); public void TeachingTip_ActionButtonClick(TeachingTip sender, object args) { diff --git a/Yugen.Mosaic.Uwp/ViewModels/SettingsViewModel.cs b/Yugen.Mosaic.Uwp/ViewModels/SettingsViewModel.cs index 7599402..9a96ee4 100644 --- a/Yugen.Mosaic.Uwp/ViewModels/SettingsViewModel.cs +++ b/Yugen.Mosaic.Uwp/ViewModels/SettingsViewModel.cs @@ -9,7 +9,7 @@ namespace Yugen.Mosaic.Uwp.ViewModels { - public class SettingsViewModel: BaseViewModel + public class SettingsViewModel : BaseViewModel { private const string STORE_REVIEWFORMAT = "ms-windows-store:REVIEW?PFN={0}"; private ElementTheme _elementTheme = ThemeSelectorService.Theme; @@ -18,8 +18,8 @@ public class SettingsViewModel: BaseViewModel public ElementTheme ElementTheme { - get { return _elementTheme; } - set { Set(ref _elementTheme, value); } + get => _elementTheme; + set => Set(ref _elementTheme, value); } public ICommand SwitchThemeCommand { diff --git a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj index 5a1d3c2..49fdd2a 100644 --- a/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj +++ b/Yugen.Mosaic.Uwp/Yugen.Mosaic.Uwp.csproj @@ -156,6 +156,7 @@ + @@ -270,7 +271,7 @@ 1.0.0-rc0001 - 1.0.0-unstable0436 + 1.0.0-beta0007 1.6.5