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..bdb6b49a92 100644
--- a/src/ImageSharp/Image.cs
+++ b/src/ImageSharp/Image.cs
@@ -44,6 +44,23 @@ namespace ImageSharp
{
}
+#if !NETSTANDARD1_1
+ ///
+ /// 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..33d6a69655 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 !NETSTANDARD1_1
+ ///
+ /// 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 !NETSTANDARD1_1
+ ///
+ /// 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)
+ {
+ 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}'.");
+ }
+
+ 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 (FileStream 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 (FileStream 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..639773377e 100644
--- a/src/ImageSharp/project.json
+++ b/src/ImageSharp/project.json
@@ -46,6 +46,27 @@
"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": {
"dependencies": {
"System.Collections": "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..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;
///
@@ -29,5 +31,101 @@ 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);
+ });
+ }
+
+ [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);
+ }
+ }
}
}
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.
///