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.
///