From 8b7923fe6b8c904b32167be1b0e3f1cafd4d557a Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Sun, 12 Feb 2017 16:09:42 +0000 Subject: [PATCH 1/5] file path based apis --- README.md | 10 +++ src/ImageSharp/Image.cs | 17 ++++ src/ImageSharp/Image/Image{TColor}.cs | 80 ++++++++++++++++++- src/ImageSharp/project.json | 24 ++++++ .../Formats/Bmp/BitmapTests.cs | 5 +- tests/ImageSharp.Tests/Image/ImageTests.cs | 31 +++++++ tests/ImageSharp.Tests/TestFile.cs | 5 ++ 7 files changed, 166 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 79f8994629..cfbd18de6e 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,16 @@ Many `Image` methods are also fluent. Here's an example of the code required to resize an image using the default Bicubic resampler then turn the colors into their grayscale equivalent using the BT709 standard matrix. +On platforms supporting netstandard 1.3+ +```csharp +using (Image image = new Image("foo.jpg")) +{ + image.Resize(image.Width / 2, image.Height / 2) + .Grayscale() + .Save("bar.jpg"); // automatic encoder selected based on extension. +} +``` +on netstandard 1.1 - 1.2 ```csharp using (FileStream stream = File.OpenRead("foo.jpg")) using (FileStream output = File.OpenWrite("bar.jpg")) diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 7adea78b24..4da9cac36e 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -44,6 +44,23 @@ namespace ImageSharp { } +#if !NO_FILE_IO + /// + /// Initializes a new instance of the class. + /// + /// + /// A file path to read image information. + /// + /// + /// The configuration providing initialization code which allows extending the library. + /// + /// Thrown if the is null. + public Image(string filePath, Configuration configuration = null) + : base(filePath, configuration) + { + } +#endif + /// /// Initializes a new instance of the class. /// diff --git a/src/ImageSharp/Image/Image{TColor}.cs b/src/ImageSharp/Image/Image{TColor}.cs index c16bba3447..ded3e376eb 100644 --- a/src/ImageSharp/Image/Image{TColor}.cs +++ b/src/ImageSharp/Image/Image{TColor}.cs @@ -63,6 +63,28 @@ namespace ImageSharp this.Load(stream); } +#if !NO_FILE_IO + /// + /// Initializes a new instance of the class. + /// + /// + /// The file containing image information. + /// + /// + /// The configuration providing initialization code which allows extending the library. + /// + /// Thrown if the is null. + public Image(string filePath, Configuration configuration = null) + : base(configuration) + { + Guard.NotNull(filePath, nameof(filePath)); + using (var fs = File.OpenRead(filePath)) + { + this.Load(fs); + } + } +#endif + /// /// Initializes a new instance of the class. /// @@ -189,11 +211,12 @@ namespace ImageSharp /// /// The stream to save the image to. /// The format to save the image as. - /// Thrown if the stream is null. + /// Thrown if the stream or format is null. /// The public Image Save(Stream stream, IImageFormat format) { Guard.NotNull(stream, nameof(stream)); + Guard.NotNull(format, nameof(format)); format.Encoder.Encode(this, stream); return this; } @@ -203,13 +226,14 @@ namespace ImageSharp /// /// The stream to save the image to. /// The encoder to save the image with. - /// Thrown if the stream is null. + /// Thrown if the stream or encoder is null. /// /// The . /// public Image Save(Stream stream, IImageEncoder encoder) { Guard.NotNull(stream, nameof(stream)); + Guard.NotNull(encoder, nameof(encoder)); encoder.Encode(this, stream); // Reset to the start of the stream. @@ -221,6 +245,58 @@ namespace ImageSharp return this; } +#if !NO_FILE_IO + /// + /// Saves the image to the given stream using the currently loaded image format. + /// + /// The file path to save the image to. + /// Thrown if the stream is null. + /// The + public Image Save(string filePath) + { + var ext = Path.GetExtension(filePath).Trim('.'); + var format = this.Configuration.ImageFormats.SingleOrDefault(f => f.SupportedExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase)); + if (format == null) + { + throw new InvalidOperationException($"No image formats have been registered for the file extension '{ext}'."); + } + + return this.Save(filePath, format); + } + + /// + /// Saves the image to the given stream using the currently loaded image format. + /// + /// The file path to save the image to. + /// The format to save the image as. + /// Thrown if the format is null. + /// The + public Image Save(string filePath, IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + using (var fs = File.Create(filePath)) + { + return this.Save(fs, format); + } + } + + /// + /// Saves the image to the given stream using the currently loaded image format. + /// + /// The file path to save the image to. + /// The encoder to save the image with. + /// Thrown if the encoder is null. + /// The + public Image Save(string filePath, IImageEncoder encoder) + { + Guard.NotNull(encoder, nameof(encoder)); + using (var fs = File.Create(filePath)) + { + return this.Save(fs, encoder); + } + } +#endif + /// public override string ToString() { diff --git a/src/ImageSharp/project.json b/src/ImageSharp/project.json index 8ad3fd71ab..a5d1bb93f6 100644 --- a/src/ImageSharp/project.json +++ b/src/ImageSharp/project.json @@ -46,7 +46,31 @@ "System.Runtime.CompilerServices.Unsafe": "4.0.0" }, "frameworks": { + "netstandard1.3": { + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tools": "4.0.1", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.1.0", + "System.IO.Compression": "4.1.0", + "System.Linq": "4.1.0", + "System.Numerics.Vectors": "4.1.1", + "System.ObjectModel": "4.0.12", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Runtime.Numerics": "4.0.1", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Tasks.Parallel": "4.0.1" + } + }, "netstandard1.1": { + "buildOptions": { + "define": [ "NO_FILE_IO" ] + }, "dependencies": { "System.Collections": "4.0.11", "System.Diagnostics.Debug": "4.0.11", diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BitmapTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BitmapTests.cs index 2eb81a6232..c1275335d2 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BitmapTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BitmapTests.cs @@ -31,10 +31,7 @@ namespace ImageSharp.Tests string filename = file.GetFileNameWithoutExtension(bitsPerPixel); using (Image image = file.CreateImage()) { - using (FileStream output = File.OpenWrite($"{path}/{filename}.bmp")) - { - image.Save(output, new BmpEncoder { BitsPerPixel = bitsPerPixel }); - } + image.Save($"{path}/{filename}.bmp", new BmpEncoder { BitsPerPixel = bitsPerPixel }); } } } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.cs b/tests/ImageSharp.Tests/Image/ImageTests.cs index c3c092e8eb..a22456e52f 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.cs @@ -29,5 +29,36 @@ namespace ImageSharp.Tests Assert.Equal(450, image.Height); } } + + [Fact] + public void ConstructorFileSystem() + { + TestFile file = TestFile.Create(TestImages.Bmp.Car); + using (Image image = new Image(file.FilePath)) + { + Assert.Equal(600, image.Width); + Assert.Equal(450, image.Height); + } + } + + [Fact] + public void ConstructorFileSystem_FileNotFound() + { + System.IO.FileNotFoundException ex = Assert.Throws( + () => + { + new Image(Guid.NewGuid().ToString()); + }); + } + + [Fact] + public void ConstructorFileSystem_NullPath() + { + ArgumentNullException ex = Assert.Throws( + () => + { + new Image(null); + }); + } } } diff --git a/tests/ImageSharp.Tests/TestFile.cs b/tests/ImageSharp.Tests/TestFile.cs index 3d66958416..891a45cec9 100644 --- a/tests/ImageSharp.Tests/TestFile.cs +++ b/tests/ImageSharp.Tests/TestFile.cs @@ -54,6 +54,11 @@ namespace ImageSharp.Tests /// public byte[] Bytes { get; } + /// + /// The file name. + /// + public string FilePath => this.file; + /// /// The file name. /// From 0c274cd87870369a760b4895fb041020266c9214 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Sun, 12 Feb 2017 19:09:11 +0000 Subject: [PATCH 2/5] improved test coverage --- tests/ImageSharp.Tests/Image/ImageTests.cs | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/ImageSharp.Tests/Image/ImageTests.cs b/tests/ImageSharp.Tests/Image/ImageTests.cs index a22456e52f..aea4330c68 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.cs @@ -7,6 +7,8 @@ namespace ImageSharp.Tests { using System; + using ImageSharp.Formats; + using Xunit; /// @@ -60,5 +62,70 @@ namespace ImageSharp.Tests new Image(null); }); } + + [Fact] + public void Save_DetecedEncoding() + { + string file = TestFile.GetPath("../../TestOutput/Save_DetecedEncoding.png"); + var dir = System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(file)); + using (Image image = new Image(10, 10)) + { + image.Save(file); + } + + var c = TestFile.Create("../../TestOutput/Save_DetecedEncoding.png"); + using (var img = c.CreateImage()) + { + Assert.IsType(img.CurrentImageFormat); + } + } + + [Fact] + public void Save_UnknownExtensionsEncoding() + { + string file = TestFile.GetPath("../../TestOutput/Save_DetecedEncoding.tmp"); + var ex = Assert.Throws( + () => + { + using (Image image = new Image(10, 10)) + { + image.Save(file); + } + }); + } + + [Fact] + public void Save_SetFormat() + { + string file = TestFile.GetPath("../../TestOutput/Save_SetFormat.dat"); + var dir = System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(file)); + using (Image image = new Image(10, 10)) + { + image.Save(file, new PngFormat()); + } + + var c = TestFile.Create("../../TestOutput/Save_SetFormat.dat"); + using (var img = c.CreateImage()) + { + Assert.IsType(img.CurrentImageFormat); + } + } + + [Fact] + public void Save_SetEncoding() + { + string file = TestFile.GetPath("../../TestOutput/Save_SetEncoding.dat"); + var dir = System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(file)); + using (Image image = new Image(10, 10)) + { + image.Save(file, new PngEncoder()); + } + + var c = TestFile.Create("../../TestOutput/Save_SetEncoding.dat"); + using (var img = c.CreateImage()) + { + Assert.IsType(img.CurrentImageFormat); + } + } } } From 593500e11b7764c1a43903e05a5a01cc31ce2e2e Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Mon, 13 Feb 2017 08:12:56 +0000 Subject: [PATCH 3/5] fix vars --- src/ImageSharp/Image/Image{TColor}.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Image/Image{TColor}.cs b/src/ImageSharp/Image/Image{TColor}.cs index ded3e376eb..75d855ad42 100644 --- a/src/ImageSharp/Image/Image{TColor}.cs +++ b/src/ImageSharp/Image/Image{TColor}.cs @@ -254,8 +254,8 @@ namespace ImageSharp /// The public Image Save(string filePath) { - var ext = Path.GetExtension(filePath).Trim('.'); - var format = this.Configuration.ImageFormats.SingleOrDefault(f => f.SupportedExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase)); + string ext = Path.GetExtension(filePath).Trim('.'); + IImageFormat format = this.Configuration.ImageFormats.SingleOrDefault(f => f.SupportedExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase)); if (format == null) { throw new InvalidOperationException($"No image formats have been registered for the file extension '{ext}'."); @@ -274,7 +274,7 @@ namespace ImageSharp public Image Save(string filePath, IImageFormat format) { Guard.NotNull(format, nameof(format)); - using (var fs = File.Create(filePath)) + using (FileStream fs = File.Create(filePath)) { return this.Save(fs, format); } @@ -290,7 +290,7 @@ namespace ImageSharp public Image Save(string filePath, IImageEncoder encoder) { Guard.NotNull(encoder, nameof(encoder)); - using (var fs = File.Create(filePath)) + using (FileStream fs = File.Create(filePath)) { return this.Save(fs, encoder); } From d58adb42471ac9551894343afe747c09e3a58e19 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 14 Feb 2017 08:40:04 +0000 Subject: [PATCH 4/5] change NO_FILE_IO to NETSTANDARD11 --- src/ImageSharp/Image.cs | 2 +- src/ImageSharp/Image/Image{TColor}.cs | 4 ++-- src/ImageSharp/project.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 4da9cac36e..284a7c29b7 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -44,7 +44,7 @@ namespace ImageSharp { } -#if !NO_FILE_IO +#if !NETSTANDARD11 /// /// Initializes a new instance of the class. /// diff --git a/src/ImageSharp/Image/Image{TColor}.cs b/src/ImageSharp/Image/Image{TColor}.cs index 75d855ad42..0931a12da6 100644 --- a/src/ImageSharp/Image/Image{TColor}.cs +++ b/src/ImageSharp/Image/Image{TColor}.cs @@ -63,7 +63,7 @@ namespace ImageSharp this.Load(stream); } -#if !NO_FILE_IO +#if !NETSTANDARD11 /// /// Initializes a new instance of the class. /// @@ -245,7 +245,7 @@ namespace ImageSharp return this; } -#if !NO_FILE_IO +#if !NETSTANDARD11 /// /// Saves the image to the given stream using the currently loaded image format. /// diff --git a/src/ImageSharp/project.json b/src/ImageSharp/project.json index a5d1bb93f6..7b2dbed08d 100644 --- a/src/ImageSharp/project.json +++ b/src/ImageSharp/project.json @@ -69,7 +69,7 @@ }, "netstandard1.1": { "buildOptions": { - "define": [ "NO_FILE_IO" ] + "define": [ "NETSTANDARD11" ] }, "dependencies": { "System.Collections": "4.0.11", From 8912faacf2387b4064cffb8c7761d311452bf5c9 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 14 Feb 2017 09:43:56 +0000 Subject: [PATCH 5/5] correct define tag --- src/ImageSharp/Image.cs | 2 +- src/ImageSharp/Image/Image{TColor}.cs | 4 ++-- src/ImageSharp/project.json | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 284a7c29b7..bdb6b49a92 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -44,7 +44,7 @@ namespace ImageSharp { } -#if !NETSTANDARD11 +#if !NETSTANDARD1_1 /// /// Initializes a new instance of the class. /// diff --git a/src/ImageSharp/Image/Image{TColor}.cs b/src/ImageSharp/Image/Image{TColor}.cs index 0931a12da6..33d6a69655 100644 --- a/src/ImageSharp/Image/Image{TColor}.cs +++ b/src/ImageSharp/Image/Image{TColor}.cs @@ -63,7 +63,7 @@ namespace ImageSharp this.Load(stream); } -#if !NETSTANDARD11 +#if !NETSTANDARD1_1 /// /// Initializes a new instance of the class. /// @@ -245,7 +245,7 @@ namespace ImageSharp return this; } -#if !NETSTANDARD11 +#if !NETSTANDARD1_1 /// /// Saves the image to the given stream using the currently loaded image format. /// diff --git a/src/ImageSharp/project.json b/src/ImageSharp/project.json index 7b2dbed08d..639773377e 100644 --- a/src/ImageSharp/project.json +++ b/src/ImageSharp/project.json @@ -68,9 +68,6 @@ } }, "netstandard1.1": { - "buildOptions": { - "define": [ "NETSTANDARD11" ] - }, "dependencies": { "System.Collections": "4.0.11", "System.Diagnostics.Debug": "4.0.11",