diff --git a/ImageSharp.sln b/ImageSharp.sln
index 9c729493b..628fa7015 100644
--- a/ImageSharp.sln
+++ b/ImageSharp.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26228.4
+VisualStudioVersion = 15.0.26228.9
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}"
ProjectSection(SolutionItems) = preProject
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
index 9f490a3a9..2bc1c8cc3 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
@@ -26,13 +26,12 @@ namespace ImageSharp.Formats
public class BmpDecoder : IImageDecoder
{
///
- public void Decode(Image image, Stream stream, IDecoderOptions options)
+ public Image Decode(Stream stream, IDecoderOptions options)
where TColor : struct, IPixel
{
- Guard.NotNull(image, "image");
Guard.NotNull(stream, "stream");
- new BmpDecoderCore().Decode(image, stream);
+ return new BmpDecoderCore().Decode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index a75031ea1..adfa4b6ac 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -48,16 +48,13 @@ namespace ImageSharp.Formats
/// the data to image.
///
/// The pixel format.
- /// The image, where the data should be set to.
- /// Cannot be null (Nothing in Visual Basic).
/// The stream, where the image should be
/// decoded from. Cannot be null (Nothing in Visual Basic).
///
- /// is null.
- /// - or -
/// is null.
///
- public void Decode(Image image, Stream stream)
+ /// The decoded image.
+ public Image Decode(Stream stream)
where TColor : struct, IPixel
{
this.currentStream = stream;
@@ -110,14 +107,14 @@ namespace ImageSharp.Formats
this.currentStream.Read(palette, 0, colorMapSize);
}
- if (this.infoHeader.Width > image.MaxWidth || this.infoHeader.Height > image.MaxHeight)
+ if (this.infoHeader.Width > Image.MaxWidth || this.infoHeader.Height > Image.MaxHeight)
{
throw new ArgumentOutOfRangeException(
$"The input bitmap '{this.infoHeader.Width}x{this.infoHeader.Height}' is "
- + $"bigger then the max allowed size '{image.MaxWidth}x{image.MaxHeight}'");
+ + $"bigger then the max allowed size '{Image.MaxWidth}x{Image.MaxHeight}'");
}
- image.InitPixels(this.infoHeader.Width, this.infoHeader.Height);
+ Image image = new Image(this.infoHeader.Width, this.infoHeader.Height);
using (PixelAccessor pixels = image.Lock())
{
@@ -151,6 +148,8 @@ namespace ImageSharp.Formats
throw new NotSupportedException("Does not support this kind of bitmap files.");
}
}
+
+ return image;
}
catch (IndexOutOfRangeException e)
{
diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs
index b1e8ba928..16b036e68 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs
@@ -14,25 +14,25 @@ namespace ImageSharp.Formats
public class GifDecoder : IImageDecoder
{
///
- public void Decode(Image image, Stream stream, IDecoderOptions options)
+ public Image Decode(Stream stream, IDecoderOptions options)
where TColor : struct, IPixel
{
IGifDecoderOptions gifOptions = GifDecoderOptions.Create(options);
- this.Decode(image, stream, gifOptions);
+ return this.Decode(stream, gifOptions);
}
///
/// Decodes the image from the specified stream to the .
///
/// The pixel format.
- /// The to decode to.
/// The containing image data.
/// The options for the decoder.
- public void Decode(Image image, Stream stream, IGifDecoderOptions options)
+ /// The image thats been decoded.
+ public Image Decode(Stream stream, IGifDecoderOptions options)
where TColor : struct, IPixel
{
- new GifDecoderCore(options).Decode(image, stream);
+ return new GifDecoderCore(options).Decode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index ab1edc2c7..22a26345f 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -27,11 +27,6 @@ namespace ImageSharp.Formats
///
private readonly IGifDecoderOptions options;
- ///
- /// The image to decode the information to.
- ///
- private Image decodedImage;
-
///
/// The currently loaded stream.
///
@@ -67,6 +62,16 @@ namespace ImageSharp.Formats
///
private GifGraphicsControlExtension graphicsControlExtension;
+ ///
+ /// The metadata
+ ///
+ private ImageMetaData metaData;
+
+ ///
+ /// The image to decode the information to.
+ ///
+ private Image image;
+
///
/// Initializes a new instance of the class.
///
@@ -79,13 +84,13 @@ namespace ImageSharp.Formats
///
/// Decodes the stream to the image.
///
- /// The image to decode to.
/// The stream containing image data.
- public void Decode(Image image, Stream stream)
+ /// The decoded image
+ public Image Decode(Stream stream)
{
try
{
- this.decodedImage = image;
+ this.metaData = new ImageMetaData();
this.currentStream = stream;
@@ -144,6 +149,8 @@ namespace ImageSharp.Formats
ArrayPool.Shared.Return(this.globalColorTable);
}
}
+
+ return this.image;
}
///
@@ -212,11 +219,13 @@ namespace ImageSharp.Formats
throw new ImageFormatException($"Invalid gif colormap size '{this.logicalScreenDescriptor.GlobalColorTableSize}'");
}
- if (this.logicalScreenDescriptor.Width > this.decodedImage.MaxWidth || this.logicalScreenDescriptor.Height > this.decodedImage.MaxHeight)
+ /* // No point doing this as the max width/height is always int.Max and that always bigger than the max size of a gif which is stored in a short.
+ if (this.logicalScreenDescriptor.Width > Image.MaxWidth || this.logicalScreenDescriptor.Height > Image.MaxHeight)
{
throw new ArgumentOutOfRangeException(
- $"The input gif '{this.logicalScreenDescriptor.Width}x{this.logicalScreenDescriptor.Height}' is bigger then the max allowed size '{this.decodedImage.MaxWidth}x{this.decodedImage.MaxHeight}'");
+ $"The input gif '{this.logicalScreenDescriptor.Width}x{this.logicalScreenDescriptor.Height}' is bigger then the max allowed size '{Image.MaxWidth}x{Image.MaxHeight}'");
}
+ */
}
///
@@ -261,7 +270,7 @@ namespace ImageSharp.Formats
{
this.currentStream.Read(commentsBuffer, 0, length);
string comments = this.options.TextEncoding.GetString(commentsBuffer, 0, length);
- this.decodedImage.MetaData.Properties.Add(new ImageProperty(GifConstants.Comments, comments));
+ this.metaData.Properties.Add(new ImageProperty(GifConstants.Comments, comments));
}
finally
{
@@ -343,14 +352,15 @@ namespace ImageSharp.Formats
if (this.previousFrame == null)
{
- this.decodedImage.MetaData.Quality = colorTableLength / 3;
+ this.metaData.Quality = colorTableLength / 3;
// This initializes the image to become fully transparent because the alpha channel is zero.
- this.decodedImage.InitPixels(imageWidth, imageHeight);
+ this.image = new Image(imageWidth, imageHeight);
+ this.image.MetaData.LoadFrom(this.metaData);
- this.SetFrameDelay(this.decodedImage.MetaData);
+ this.SetFrameDelay(this.metaData);
- image = this.decodedImage;
+ image = this.image;
}
else
{
@@ -368,7 +378,7 @@ namespace ImageSharp.Formats
this.RestoreToBackground(image);
- this.decodedImage.Frames.Add(currentFrame);
+ this.image.Frames.Add(currentFrame);
}
int i = 0;
@@ -441,7 +451,7 @@ namespace ImageSharp.Formats
return;
}
- this.previousFrame = currentFrame == null ? this.decodedImage.ToFrame() : currentFrame;
+ this.previousFrame = currentFrame == null ? this.image.ToFrame() : currentFrame;
if (this.graphicsControlExtension != null &&
this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground)
@@ -462,8 +472,8 @@ namespace ImageSharp.Formats
}
// Optimization for when the size of the frame is the same as the image size.
- if (this.restoreArea.Value.Width == this.decodedImage.Width &&
- this.restoreArea.Value.Height == this.decodedImage.Height)
+ if (this.restoreArea.Value.Width == this.image.Width &&
+ this.restoreArea.Value.Height == this.image.Height)
{
using (PixelAccessor pixelAccessor = frame.Lock())
{
diff --git a/src/ImageSharp/Formats/IImageDecoder.cs b/src/ImageSharp/Formats/IImageDecoder.cs
index df98870dd..c4a9cf8c3 100644
--- a/src/ImageSharp/Formats/IImageDecoder.cs
+++ b/src/ImageSharp/Formats/IImageDecoder.cs
@@ -17,10 +17,10 @@ namespace ImageSharp.Formats
/// Decodes the image from the specified stream to the .
///
/// The pixel format.
- /// The to decode to.
/// The containing image data.
/// The options for the decoder.
- void Decode(Image image, Stream stream, IDecoderOptions options)
+ /// The decoded image
+ Image Decode(Stream stream, IDecoderOptions options)
where TColor : struct, IPixel;
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
index eeb371d1e..3a91f8010 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
@@ -14,15 +14,14 @@ namespace ImageSharp.Formats
public class JpegDecoder : IImageDecoder
{
///
- public void Decode(Image image, Stream stream, IDecoderOptions options)
+ public Image Decode(Stream stream, IDecoderOptions options)
where TColor : struct, IPixel
{
- Guard.NotNull(image, "image");
Guard.NotNull(stream, "stream");
using (JpegDecoderCore decoder = new JpegDecoderCore(options))
{
- decoder.Decode(image, stream, false);
+ return decoder.Decode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
index f1b85fa0b..fa656e71e 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
@@ -180,18 +180,30 @@ namespace ImageSharp.Formats
/// the data to image.
///
/// The pixel format.
- /// The image, where the data should be set to.
/// The stream, where the image should be.
- /// Whether to decode metadata only.
- public void Decode(Image image, Stream stream, bool metadataOnly)
+ /// The decoded image.
+ public Image Decode(Stream stream)
where TColor : struct, IPixel
{
- this.ProcessStream(image, stream, metadataOnly);
- if (!metadataOnly)
- {
- this.ProcessBlocksIntoJpegImageChannels();
- this.ConvertJpegPixelsToImagePixels(image);
- }
+ ImageMetaData metadata = new ImageMetaData();
+ this.ProcessStream(metadata, stream, false);
+ this.ProcessBlocksIntoJpegImageChannels();
+ Image image = this.ConvertJpegPixelsToImagePixels(metadata);
+
+ return image;
+ }
+
+ ///
+ /// Decodes the image from the specified and sets
+ /// the data to image.
+ ///
+ /// The stream, where the image should be.
+ /// The image metadata.
+ public ImageMetaData DecodeMetaData(Stream stream)
+ {
+ ImageMetaData metadata = new ImageMetaData();
+ this.ProcessStream(metadata, stream, true);
+ return metadata;
}
///
@@ -276,12 +288,10 @@ namespace ImageSharp.Formats
///
/// Read metadata from stream and read the blocks in the scans into .
///
- /// The pixel type
- /// The
+ /// The metadata
/// The stream
/// Whether to decode metadata only.
- private void ProcessStream(Image image, Stream stream, bool metadataOnly)
- where TColor : struct, IPixel
+ private void ProcessStream(ImageMetaData metadata, Stream stream, bool metadataOnly)
{
this.InputStream = stream;
this.InputProcessor = new InputProcessor(stream, this.Temp);
@@ -429,7 +439,7 @@ namespace ImageSharp.Formats
this.ProcessApplicationHeader(remaining);
break;
case JpegConstants.Markers.APP1:
- this.ProcessApp1Marker(remaining, image);
+ this.ProcessApp1Marker(remaining, metadata);
break;
case JpegConstants.Markers.APP14:
this.ProcessApp14Marker(remaining);
@@ -496,13 +506,18 @@ namespace ImageSharp.Formats
/// Convert the pixel data in and/or into pixels of
///
/// The pixel type
- /// The destination image
- private void ConvertJpegPixelsToImagePixels(Image image)
+ /// The metadata for the image.
+ /// The decoded image.
+ private Image ConvertJpegPixelsToImagePixels(ImageMetaData metadata)
where TColor : struct, IPixel
{
+ Image image = new Image(this.ImageWidth, this.ImageHeight);
+ image.MetaData.LoadFrom(metadata);
+
if (this.grayImage.IsInitialized)
{
- this.ConvertFromGrayScale(this.ImageWidth, this.ImageHeight, image);
+ this.ConvertFromGrayScale(image);
+ return image;
}
else if (this.ycbcrImage != null)
{
@@ -519,27 +534,27 @@ namespace ImageSharp.Formats
// TODO: YCbCrA?
if (this.adobeTransform == JpegConstants.Adobe.ColorTransformYcck)
{
- this.ConvertFromYcck(this.ImageWidth, this.ImageHeight, image);
+ this.ConvertFromYcck(image);
}
else if (this.adobeTransform == JpegConstants.Adobe.ColorTransformUnknown)
{
// Assume CMYK
- this.ConvertFromCmyk(this.ImageWidth, this.ImageHeight, image);
+ this.ConvertFromCmyk(image);
}
- return;
+ return image;
}
if (this.ComponentCount == 3)
{
if (this.IsRGB())
{
- this.ConvertFromRGB(this.ImageWidth, this.ImageHeight, image);
- return;
+ this.ConvertFromRGB(image);
+ return image;
}
- this.ConvertFromYCbCr(this.ImageWidth, this.ImageHeight, image);
- return;
+ this.ConvertFromYCbCr(image);
+ return image;
}
throw new ImageFormatException("JpegDecoder only supports RGB, CMYK and Grayscale color spaces.");
@@ -582,28 +597,24 @@ namespace ImageSharp.Formats
/// Converts the image from the original CMYK image pixels.
///
/// The pixel format.
- /// The image width.
- /// The image height.
/// The image.
- private void ConvertFromCmyk(int width, int height, Image image)
+ private void ConvertFromCmyk(Image image)
where TColor : struct, IPixel
{
int scale = this.ComponentArray[0].HorizontalFactor / this.ComponentArray[1].HorizontalFactor;
- image.InitPixels(width, height);
-
using (PixelAccessor pixels = image.Lock())
{
Parallel.For(
0,
- height,
+ image.Height,
y =>
{
// TODO: Simplify + optimize + share duplicate code across converter methods
int yo = this.ycbcrImage.GetRowYOffset(y);
int co = this.ycbcrImage.GetRowCOffset(y);
- for (int x = 0; x < width; x++)
+ for (int x = 0; x < image.Width; x++)
{
byte cyan = this.ycbcrImage.YChannel.Pixels[yo + x];
byte magenta = this.ycbcrImage.CbChannel.Pixels[co + (x / scale)];
@@ -623,24 +634,20 @@ namespace ImageSharp.Formats
/// Converts the image from the original grayscale image pixels.
///
/// The pixel format.
- /// The image width.
- /// The image height.
/// The image.
- private void ConvertFromGrayScale(int width, int height, Image image)
+ private void ConvertFromGrayScale(Image image)
where TColor : struct, IPixel
{
- image.InitPixels(width, height);
-
using (PixelAccessor pixels = image.Lock())
{
Parallel.For(
0,
- height,
+ image.Height,
image.Configuration.ParallelOptions,
y =>
{
int yoff = this.grayImage.GetRowOffset(y);
- for (int x = 0; x < width; x++)
+ for (int x = 0; x < image.Width; x++)
{
byte rgb = this.grayImage.Pixels[yoff + x];
@@ -658,20 +665,17 @@ namespace ImageSharp.Formats
/// Converts the image from the original RBG image pixels.
///
/// The pixel format.
- /// The image width.
- /// The height.
/// The image.
- private void ConvertFromRGB(int width, int height, Image image)
+ private void ConvertFromRGB(Image image)
where TColor : struct, IPixel
{
int scale = this.ComponentArray[0].HorizontalFactor / this.ComponentArray[1].HorizontalFactor;
- image.InitPixels(width, height);
using (PixelAccessor pixels = image.Lock())
{
Parallel.For(
0,
- height,
+ image.Height,
image.Configuration.ParallelOptions,
y =>
{
@@ -679,7 +683,7 @@ namespace ImageSharp.Formats
int yo = this.ycbcrImage.GetRowYOffset(y);
int co = this.ycbcrImage.GetRowCOffset(y);
- for (int x = 0; x < width; x++)
+ for (int x = 0; x < image.Width; x++)
{
byte red = this.ycbcrImage.YChannel.Pixels[yo + x];
byte green = this.ycbcrImage.CbChannel.Pixels[co + (x / scale)];
@@ -699,20 +703,16 @@ namespace ImageSharp.Formats
/// Converts the image from the original YCbCr image pixels.
///
/// The pixel format.
- /// The image width.
- /// The image height.
/// The image.
- private void ConvertFromYCbCr(int width, int height, Image image)
+ private void ConvertFromYCbCr(Image image)
where TColor : struct, IPixel
{
int scale = this.ComponentArray[0].HorizontalFactor / this.ComponentArray[1].HorizontalFactor;
- image.InitPixels(width, height);
-
using (PixelAccessor pixels = image.Lock())
{
Parallel.For(
0,
- height,
+ image.Height,
image.Configuration.ParallelOptions,
y =>
{
@@ -720,7 +720,7 @@ namespace ImageSharp.Formats
int yo = this.ycbcrImage.GetRowYOffset(y);
int co = this.ycbcrImage.GetRowCOffset(y);
- for (int x = 0; x < width; x++)
+ for (int x = 0; x < image.Width; x++)
{
byte yy = this.ycbcrImage.YChannel.Pixels[yo + x];
byte cb = this.ycbcrImage.CbChannel.Pixels[co + (x / scale)];
@@ -740,28 +740,24 @@ namespace ImageSharp.Formats
/// Converts the image from the original YCCK image pixels.
///
/// The pixel format.
- /// The image width.
- /// The image height.
/// The image.
- private void ConvertFromYcck(int width, int height, Image image)
+ private void ConvertFromYcck(Image image)
where TColor : struct, IPixel
{
int scale = this.ComponentArray[0].HorizontalFactor / this.ComponentArray[1].HorizontalFactor;
- image.InitPixels(width, height);
-
using (PixelAccessor pixels = image.Lock())
{
Parallel.For(
0,
- height,
+ image.Height,
y =>
{
// TODO: Simplify + optimize + share duplicate code across converter methods
int yo = this.ycbcrImage.GetRowYOffset(y);
int co = this.ycbcrImage.GetRowCOffset(y);
- for (int x = 0; x < width; x++)
+ for (int x = 0; x < image.Width; x++)
{
byte yy = this.ycbcrImage.YChannel.Pixels[yo + x];
byte cb = this.ycbcrImage.CbChannel.Pixels[co + (x / scale)];
@@ -959,11 +955,9 @@ namespace ImageSharp.Formats
///
/// Processes the App1 marker retrieving any stored metadata
///
- /// The pixel format.
/// The remaining bytes in the segment block.
- /// The image.
- private void ProcessApp1Marker(int remaining, Image image)
- where TColor : struct, IPixel
+ /// The image.
+ private void ProcessApp1Marker(int remaining, ImageMetaData metadata)
{
if (remaining < 6 || this.options.IgnoreMetadata)
{
@@ -978,7 +972,7 @@ namespace ImageSharp.Formats
&& profile[5] == '\0')
{
this.isExif = true;
- image.MetaData.ExifProfile = new ExifProfile(profile);
+ metadata.ExifProfile = new ExifProfile(profile);
}
}
diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs
index d527e1654..5b7d97fc7 100644
--- a/src/ImageSharp/Formats/Png/PngDecoder.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoder.cs
@@ -31,25 +31,25 @@ namespace ImageSharp.Formats
public class PngDecoder : IImageDecoder
{
///
- public void Decode(Image image, Stream stream, IDecoderOptions options)
+ public Image Decode(Stream stream, IDecoderOptions options)
where TColor : struct, IPixel
{
IPngDecoderOptions pngOptions = PngDecoderOptions.Create(options);
- this.Decode(image, stream, pngOptions);
+ return this.Decode(stream, pngOptions);
}
///
/// Decodes the image from the specified stream to the .
///
/// The pixel format.
- /// The to decode to.
/// The containing image data.
/// The options for the decoder.
- public void Decode(Image image, Stream stream, IPngDecoderOptions options)
+ /// The decoded image.
+ public Image Decode(Stream stream, IPngDecoderOptions options)
where TColor : struct, IPixel
{
- new PngDecoderCore(options).Decode(image, stream);
+ return new PngDecoderCore(options).Decode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index fd03ed39b..dadf7ab7d 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -148,7 +148,6 @@ namespace ImageSharp.Formats
/// Decodes the stream to the image.
///
/// The pixel format.
- /// The image to decode to.
/// The stream containing image data.
///
/// Thrown if the stream does not contain and end chunk.
@@ -156,10 +155,11 @@ namespace ImageSharp.Formats
///
/// Thrown if the image is larger than the maximum allowable size.
///
- public void Decode(Image image, Stream stream)
+ /// The decoded image
+ public Image Decode(Stream stream)
where TColor : struct, IPixel
{
- Image currentImage = image;
+ ImageMetaData metadata = new ImageMetaData();
this.currentStream = stream;
this.currentStream.Skip(8);
@@ -177,7 +177,7 @@ namespace ImageSharp.Formats
this.ValidateHeader();
break;
case PngChunkTypes.Physical:
- this.ReadPhysicalChunk(currentImage, currentChunk.Data);
+ this.ReadPhysicalChunk(metadata, currentChunk.Data);
break;
case PngChunkTypes.Data:
dataStream.Write(currentChunk.Data, 0, currentChunk.Length);
@@ -186,7 +186,7 @@ namespace ImageSharp.Formats
byte[] pal = new byte[currentChunk.Length];
Buffer.BlockCopy(currentChunk.Data, 0, pal, 0, currentChunk.Length);
this.palette = pal;
- image.MetaData.Quality = pal.Length / 3;
+ metadata.Quality = pal.Length / 3;
break;
case PngChunkTypes.PaletteAlpha:
byte[] alpha = new byte[currentChunk.Length];
@@ -194,7 +194,7 @@ namespace ImageSharp.Formats
this.paletteAlpha = alpha;
break;
case PngChunkTypes.Text:
- this.ReadTextChunk(currentImage, currentChunk.Data, currentChunk.Length);
+ this.ReadTextChunk(metadata, currentChunk.Data, currentChunk.Length);
break;
case PngChunkTypes.End:
this.isEndChunkReached = true;
@@ -208,17 +208,20 @@ namespace ImageSharp.Formats
}
}
- if (this.header.Width > image.MaxWidth || this.header.Height > image.MaxHeight)
+ if (this.header.Width > Image.MaxWidth || this.header.Height > Image.MaxHeight)
{
- throw new ArgumentOutOfRangeException($"The input png '{this.header.Width}x{this.header.Height}' is bigger than the max allowed size '{image.MaxWidth}x{image.MaxHeight}'");
+ throw new ArgumentOutOfRangeException($"The input png '{this.header.Width}x{this.header.Height}' is bigger than the max allowed size '{Image.MaxWidth}x{Image.MaxHeight}'");
}
- image.InitPixels(this.header.Width, this.header.Height);
+ Image image = new Image(this.header.Width, this.header.Height);
+ image.MetaData.LoadFrom(metadata);
using (PixelAccessor pixels = image.Lock())
{
this.ReadScanlines(dataStream, pixels);
}
+
+ return image;
}
}
@@ -270,18 +273,16 @@ namespace ImageSharp.Formats
///
/// Reads the data chunk containing physical dimension data.
///
- /// The pixel format.
- /// The image to read to.
+ /// The metadata to read to.
/// The data containing physical data.
- private void ReadPhysicalChunk(Image image, byte[] data)
- where TColor : struct, IPixel
+ private void ReadPhysicalChunk(ImageMetaData metadata, byte[] data)
{
data.ReverseBytes(0, 4);
data.ReverseBytes(4, 4);
// 39.3700787 = inches in a meter.
- image.MetaData.HorizontalResolution = BitConverter.ToInt32(data, 0) / 39.3700787d;
- image.MetaData.VerticalResolution = BitConverter.ToInt32(data, 4) / 39.3700787d;
+ metadata.HorizontalResolution = BitConverter.ToInt32(data, 0) / 39.3700787d;
+ metadata.VerticalResolution = BitConverter.ToInt32(data, 4) / 39.3700787d;
}
///
@@ -768,12 +769,10 @@ namespace ImageSharp.Formats
///
/// Reads a text chunk containing image properties from the data.
///
- /// The pixel format.
- /// The image to decode to.
+ /// The metadata to decode to.
/// The containing data.
/// The maximum length to read.
- private void ReadTextChunk(Image image, byte[] data, int length)
- where TColor : struct, IPixel
+ private void ReadTextChunk(ImageMetaData metadata, byte[] data, int length)
{
if (this.options.IgnoreMetadata)
{
@@ -794,7 +793,7 @@ namespace ImageSharp.Formats
string name = this.options.TextEncoding.GetString(data, 0, zeroIndex);
string value = this.options.TextEncoding.GetString(data, zeroIndex + 1, length - zeroIndex - 1);
- image.MetaData.Properties.Add(new ImageProperty(name, value));
+ metadata.Properties.Add(new ImageProperty(name, value));
}
///
diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs
new file mode 100644
index 000000000..f31f2c0a5
--- /dev/null
+++ b/src/ImageSharp/Image.Decode.cs
@@ -0,0 +1,67 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp
+{
+ using System;
+ using System.Buffers;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using Formats;
+
+ ///
+ /// Represents an image. Each pixel is a made up four 8-bit components red, green, blue, and alpha
+ /// packed into a single unsigned integer value.
+ ///
+ public sealed partial class Image
+ {
+ ///
+ /// Decodes the image stream to the current image.
+ ///
+ /// The pixel format.
+ /// The stream.
+ /// The options for the decoder.
+ /// the configuration.
+ /// The decoded image
+ ///
+ /// [true] if can successfull decode the image otherwise [false].
+ ///
+ private static bool Decode(Stream stream, IDecoderOptions options, Configuration config, out Image img)
+ where TColor : struct, IPixel
+ {
+ img = null;
+ int maxHeaderSize = config.MaxHeaderSize;
+ if (maxHeaderSize <= 0)
+ {
+ return false;
+ }
+
+ IImageFormat format;
+ byte[] header = ArrayPool.Shared.Rent(maxHeaderSize);
+ try
+ {
+ long startPosition = stream.Position;
+ stream.Read(header, 0, maxHeaderSize);
+ stream.Position = startPosition;
+ format = config.ImageFormats.FirstOrDefault(x => x.IsSupportedFileFormat(header));
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(header);
+ }
+
+ if (format == null)
+ {
+ return false;
+ }
+
+ img = format.Decoder.Decode(stream, options);
+ img.CurrentImageFormat = format;
+ return true;
+ }
+ }
+}
diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs
new file mode 100644
index 000000000..e68a57fe7
--- /dev/null
+++ b/src/ImageSharp/Image.FromBytes.cs
@@ -0,0 +1,148 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp
+{
+ using System;
+ using System.Buffers;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using Formats;
+
+ ///
+ /// Represents an image. Each pixel is a made up four 8-bit components red, green, blue, and alpha
+ /// packed into a single unsigned integer value.
+ ///
+ public sealed partial class Image
+ {
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(byte[] stream)
+ {
+ return Load(stream, null, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ /// The options for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(byte[] stream, IDecoderOptions options)
+ {
+ return Load(stream, options, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ /// The config for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(byte[] stream, Configuration config)
+ {
+ return Load(stream, null, config);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ /// The options for the decoder.
+ /// The configuration options.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(byte[] stream, IDecoderOptions options, Configuration config)
+ {
+ using (MemoryStream ms = new MemoryStream(stream))
+ {
+ return Load(ms, options, config);
+ }
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(byte[] stream)
+ where TColor : struct, IPixel
+ {
+ return Load(stream, null, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ /// The options for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(byte[] stream, IDecoderOptions options)
+ where TColor : struct, IPixel
+ {
+ return Load(stream, options, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ /// The config for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(byte[] stream, Configuration config)
+ where TColor : struct, IPixel
+ {
+ return Load(stream, null, config);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ /// The options for the decoder.
+ /// The configuration options.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(byte[] stream, IDecoderOptions options, Configuration config)
+ where TColor : struct, IPixel
+ {
+ using (MemoryStream ms = new MemoryStream(stream))
+ {
+ return Load(ms, options, config);
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Image.FromFile.cs b/src/ImageSharp/Image.FromFile.cs
new file mode 100644
index 000000000..b0adb1f96
--- /dev/null
+++ b/src/ImageSharp/Image.FromFile.cs
@@ -0,0 +1,148 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp
+{
+ using System;
+ using System.Buffers;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using Formats;
+
+#if !NETSTANDARD1_1
+ ///
+ /// Represents an image. Each pixel is a made up four 8-bit components red, green, blue, and alpha
+ /// packed into a single unsigned integer value.
+ ///
+ public sealed partial class Image
+ {
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(string stream)
+ {
+ return Load(stream, null, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ /// The options for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(string stream, IDecoderOptions options)
+ {
+ return Load(stream, options, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ /// The config for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(string stream, Configuration config)
+ {
+ return Load(stream, null, config);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ /// The options for the decoder.
+ /// The configuration options.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(string stream, IDecoderOptions options, Configuration config)
+ {
+ return new Image(Image.Load(stream, options, config));
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(string stream)
+ where TColor : struct, IPixel
+ {
+ return Load(stream, null, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ /// The options for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(string stream, IDecoderOptions options)
+ where TColor : struct, IPixel
+ {
+ return Load(stream, options, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ /// The config for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(string stream, Configuration config)
+ where TColor : struct, IPixel
+ {
+ return Load(stream, null, config);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ /// The options for the decoder.
+ /// The configuration options.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(string stream, IDecoderOptions options, Configuration config)
+ where TColor : struct, IPixel
+ {
+ config = config ?? Configuration.Default;
+ using (Stream s = config.FileSystem.OpenRead(stream))
+ {
+ return Load(s, options, config);
+ }
+ }
+ }
+#endif
+}
diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs
new file mode 100644
index 000000000..36309db5b
--- /dev/null
+++ b/src/ImageSharp/Image.FromStream.cs
@@ -0,0 +1,184 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp
+{
+ using System;
+ using System.Buffers;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using Formats;
+
+ ///
+ /// Represents an image. Each pixel is a made up four 8-bit components red, green, blue, and alpha
+ /// packed into a single unsigned integer value.
+ ///
+ public sealed partial class Image
+ {
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(Stream stream)
+ {
+ return Load(stream, null, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ /// The options for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(Stream stream, IDecoderOptions options)
+ {
+ return Load(stream, options, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ /// The config for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(Stream stream, Configuration config)
+ {
+ return Load(stream, null, config);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The stream containing image information.
+ /// The options for the decoder.
+ /// The configuration options.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(Stream stream, IDecoderOptions options, Configuration config)
+ {
+ return new Image(Load(stream, options, config));
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(Stream stream)
+ where TColor : struct, IPixel
+ {
+ return Load(stream, null, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ /// The options for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(Stream stream, IDecoderOptions options)
+ where TColor : struct, IPixel
+ {
+ return Load(stream, options, null);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ /// The config for the decoder.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(Stream stream, Configuration config)
+ where TColor : struct, IPixel
+ {
+ return Load(stream, null, config);
+ }
+
+ ///
+ /// Loads the image from the given stream.
+ ///
+ /// The pixel format.
+ /// The stream containing image information.
+ /// The options for the decoder.
+ /// The configuration options.
+ ///
+ /// Thrown if the stream is not readable nor seekable.
+ ///
+ /// The image
+ public static Image Load(Stream stream, IDecoderOptions options, Configuration config)
+ where TColor : struct, IPixel
+ {
+ config = config ?? Configuration.Default;
+
+ if (!config.ImageFormats.Any())
+ {
+ throw new InvalidOperationException("No image formats have been configured.");
+ }
+
+ if (!stream.CanRead)
+ {
+ throw new NotSupportedException("Cannot read from the stream.");
+ }
+
+ if (stream.CanSeek)
+ {
+ if (Decode(stream, options, config, out Image img))
+ {
+ return img;
+ }
+ }
+ else
+ {
+ // We want to be able to load images from things like HttpContext.Request.Body
+ using (MemoryStream ms = new MemoryStream())
+ {
+ stream.CopyTo(ms);
+ ms.Position = 0;
+
+ if (Decode(ms, options, config, out Image img))
+ {
+ return img;
+ }
+ }
+ }
+
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.AppendLine("Image cannot be loaded. Available formats:");
+
+ foreach (IImageFormat format in config.ImageFormats)
+ {
+ stringBuilder.AppendLine("-" + format);
+ }
+
+ throw new NotSupportedException(stringBuilder.ToString());
+ }
+ }
+}
diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs
index 8bfd8ee1a..352107021 100644
--- a/src/ImageSharp/Image.cs
+++ b/src/ImageSharp/Image.cs
@@ -5,6 +5,7 @@
namespace ImageSharp
{
+ using System;
using System.Diagnostics;
using System.IO;
@@ -15,7 +16,7 @@ namespace ImageSharp
/// packed into a single unsigned integer value.
///
[DebuggerDisplay("Image: {Width}x{Height}")]
- public sealed class Image : Image
+ public sealed partial class Image : Image
{
///
/// Initializes a new instance of the class
@@ -26,190 +27,19 @@ namespace ImageSharp
///
/// The configuration providing initialization code which allows extending the library.
///
- public Image(int width, int height, Configuration configuration = null)
+ public Image(int width, int height, Configuration configuration)
: base(width, height, configuration)
{
}
///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The stream containing image information.
- ///
- /// Thrown if the is null.
- public Image(Stream stream)
- : base(stream, null, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The stream containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- /// Thrown if the is null.
- public Image(Stream stream, IDecoderOptions options)
- : base(stream, options, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The stream containing image information.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(Stream stream, Configuration configuration)
- : base(stream, null, configuration)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The stream containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(Stream stream, IDecoderOptions options, Configuration configuration)
- : base(stream, options, configuration)
- {
- }
-
-#if !NETSTANDARD1_1
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// A file path to read image information.
- ///
- /// Thrown if the is null.
- public Image(string filePath)
- : base(filePath, null, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// A file path to read image information.
- ///
- ///
- /// The options for the decoder.
- ///
- /// Thrown if the is null.
- public Image(string filePath, IDecoderOptions options)
- : base(filePath, options, null)
- {
- }
-
- ///
- /// 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)
- : base(filePath, null, configuration)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// A file path to read image information.
- ///
- ///
- /// The options for the decoder.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(string filePath, IDecoderOptions options, Configuration configuration)
- : base(filePath, options, configuration)
- {
- }
-#endif
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The byte array containing image information.
- ///
- /// Thrown if the is null.
- public Image(byte[] bytes)
- : base(bytes, null, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The byte array containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- /// Thrown if the is null.
- public Image(byte[] bytes, IDecoderOptions options)
- : base(bytes, options, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The byte array containing image information.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(byte[] bytes, Configuration configuration)
- : base(bytes, null, configuration)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class
+ /// with the height and the width of the image.
///
- ///
- /// The byte array containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(byte[] bytes, IDecoderOptions options, Configuration configuration)
- : base(bytes, options, configuration)
+ /// The width of the image in pixels.
+ /// The height of the image in pixels.
+ public Image(int width, int height)
+ : this(width, height, null)
{
}
@@ -219,7 +49,7 @@ namespace ImageSharp
///
/// The other image, where the clone should be made from.
/// is null.
- public Image(Image other)
+ internal Image(Image other)
: base(other)
{
}
diff --git a/src/ImageSharp/Image/IImageBase.cs b/src/ImageSharp/Image/IImageBase.cs
index 707fea235..393d83077 100644
--- a/src/ImageSharp/Image/IImageBase.cs
+++ b/src/ImageSharp/Image/IImageBase.cs
@@ -15,16 +15,6 @@ namespace ImageSharp
///
Rectangle Bounds { get; }
- ///
- /// Gets or sets the maximum allowable width in pixels.
- ///
- int MaxWidth { get; set; }
-
- ///
- /// Gets or sets the maximum allowable height in pixels.
- ///
- int MaxHeight { get; set; }
-
///
/// Gets the width in pixels.
///
diff --git a/src/ImageSharp/Image/IImageBase{TColor}.cs b/src/ImageSharp/Image/IImageBase{TColor}.cs
index e894fba4a..14bdffc67 100644
--- a/src/ImageSharp/Image/IImageBase{TColor}.cs
+++ b/src/ImageSharp/Image/IImageBase{TColor}.cs
@@ -21,16 +21,6 @@ namespace ImageSharp
///
TColor[] Pixels { get; }
- ///
- /// Sets the size of the pixel array of the image to the given width and height.
- ///
- /// The new width of the image. Must be greater than zero.
- /// The new height of the image. Must be greater than zero.
- ///
- /// Thrown if either or are less than or equal to 0.
- ///
- void InitPixels(int width, int height);
-
///
/// Locks the image providing access to the pixels.
///
diff --git a/src/ImageSharp/Image/ImageBase{TColor}.cs b/src/ImageSharp/Image/ImageBase{TColor}.cs
index 878ba09b3..cfce7184b 100644
--- a/src/ImageSharp/Image/ImageBase{TColor}.cs
+++ b/src/ImageSharp/Image/ImageBase{TColor}.cs
@@ -18,6 +18,16 @@ namespace ImageSharp
public abstract class ImageBase : IImageBase
where TColor : struct, IPixel
{
+ ///
+ /// Gets or sets the maximum allowable width in pixels.
+ ///
+ public const int MaxWidth = int.MaxValue;
+
+ ///
+ /// Gets or sets the maximum allowable height in pixels.
+ ///
+ public const int MaxHeight = int.MaxValue;
+
///
/// The image pixels
///
@@ -40,7 +50,7 @@ namespace ImageSharp
///
/// The configuration providing initialization code which allows extending the library.
///
- protected ImageBase(Configuration configuration = null)
+ protected ImageBase(Configuration configuration)
{
this.Configuration = configuration ?? Configuration.Default;
}
@@ -56,10 +66,15 @@ namespace ImageSharp
///
/// Thrown if either or are less than or equal to 0.
///
- protected ImageBase(int width, int height, Configuration configuration = null)
+ protected ImageBase(int width, int height, Configuration configuration)
+ : this(configuration)
{
- this.Configuration = configuration ?? Configuration.Default;
- this.InitPixels(width, height);
+ Guard.MustBeGreaterThan(width, 0, nameof(width));
+ Guard.MustBeGreaterThan(height, 0, nameof(height));
+
+ this.Width = width;
+ this.Height = height;
+ this.RentPixels();
this.ClearPixels();
}
@@ -73,6 +88,7 @@ namespace ImageSharp
/// Thrown if the given is null.
///
protected ImageBase(ImageBase other)
+ : this(other.Configuration)
{
Guard.NotNull(other, nameof(other), "Other image cannot be null.");
@@ -90,12 +106,6 @@ namespace ImageSharp
}
}
- ///
- public int MaxWidth { get; set; } = int.MaxValue;
-
- ///
- public int MaxHeight { get; set; } = int.MaxValue;
-
///
public TColor[] Pixels => this.pixelBuffer;
@@ -139,17 +149,6 @@ namespace ImageSharp
GC.SuppressFinalize(this);
}
- ///
- public void InitPixels(int width, int height)
- {
- Guard.MustBeGreaterThan(width, 0, nameof(width));
- Guard.MustBeGreaterThan(height, 0, nameof(height));
-
- this.Width = width;
- this.Height = height;
- this.RentPixels();
- }
-
///
public PixelAccessor Lock()
{
diff --git a/src/ImageSharp/Image/Image{TColor}.cs b/src/ImageSharp/Image/Image{TColor}.cs
index 34724cc97..82991948c 100644
--- a/src/ImageSharp/Image/Image{TColor}.cs
+++ b/src/ImageSharp/Image/Image{TColor}.cs
@@ -35,7 +35,7 @@ namespace ImageSharp
///
/// The configuration providing initialization code which allows extending the library.
///
- public Image(int width, int height, Configuration configuration = null)
+ public Image(int width, int height, Configuration configuration)
: base(width, height, configuration)
{
if (!this.Configuration.ImageFormats.Any())
@@ -43,203 +43,19 @@ namespace ImageSharp
throw new InvalidOperationException("No image formats have been configured.");
}
+ this.MetaData = new ImageMetaData();
this.CurrentImageFormat = this.Configuration.ImageFormats.First();
}
///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The stream containing image information.
- ///
- /// Thrown if the is null.
- public Image(Stream stream)
- : this(stream, null, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The stream containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- /// Thrown if the is null.
- public Image(Stream stream, IDecoderOptions options)
- : this(stream, options, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The stream containing image information.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(Stream stream, Configuration configuration)
- : this(stream, null, configuration)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The stream containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(Stream stream, IDecoderOptions options, Configuration configuration)
- : base(configuration)
- {
- Guard.NotNull(stream, nameof(stream));
- this.Load(stream, options);
- }
-
-#if !NETSTANDARD1_1
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The file containing image information.
- ///
- /// Thrown if the is null.
- public Image(string filePath)
- : this(filePath, null, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The file containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- /// Thrown if the is null.
- public Image(string filePath, IDecoderOptions options)
- : this(filePath, options, null)
- {
- }
-
- ///
- /// 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)
- : this(filePath, null, configuration)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The file containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(string filePath, IDecoderOptions options, Configuration configuration)
- : base(configuration)
- {
- Guard.NotNull(filePath, nameof(filePath));
-
- using (Stream fs = this.Configuration.FileSystem.OpenRead(filePath))
- {
- this.Load(fs, options);
- }
- }
-#endif
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The byte array containing image information.
- ///
- /// Thrown if the is null.
- public Image(byte[] bytes)
- : this(bytes, null, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The byte array containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- /// Thrown if the is null.
- public Image(byte[] bytes, IDecoderOptions options)
- : this(bytes, options, null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The byte array containing image information.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(byte[] bytes, Configuration configuration)
- : this(bytes, null, configuration)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class
+ /// with the height and the width of the image.
///
- ///
- /// The byte array containing image information.
- ///
- ///
- /// The options for the decoder.
- ///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
- /// Thrown if the is null.
- public Image(byte[] bytes, IDecoderOptions options, Configuration configuration)
- : base(configuration)
+ /// The width of the image in pixels.
+ /// The height of the image in pixels.
+ public Image(int width, int height)
+ : this(width, height, null)
{
- Guard.NotNull(bytes, nameof(bytes));
-
- using (MemoryStream stream = new MemoryStream(bytes, false))
- {
- this.Load(stream, options);
- }
}
///
@@ -271,7 +87,6 @@ namespace ImageSharp
public Image(ImageBase other)
: base(other)
{
- this.CopyProperties(other);
}
///
@@ -588,103 +403,8 @@ namespace ImageSharp
///
private void CopyProperties(IImage other)
{
- base.CopyProperties(other);
-
this.CurrentImageFormat = other.CurrentImageFormat;
this.MetaData = new ImageMetaData(other.MetaData);
}
-
- ///
- /// Loads the image from the given stream.
- ///
- /// The stream containing image information.
- /// The options for the decoder.
- ///
- /// Thrown if the stream is not readable nor seekable.
- ///
- private void Load(Stream stream, IDecoderOptions options)
- {
- if (!this.Configuration.ImageFormats.Any())
- {
- throw new InvalidOperationException("No image formats have been configured.");
- }
-
- if (!stream.CanRead)
- {
- throw new NotSupportedException("Cannot read from the stream.");
- }
-
- if (stream.CanSeek)
- {
- if (this.Decode(stream, options))
- {
- return;
- }
- }
- else
- {
- // We want to be able to load images from things like HttpContext.Request.Body
- using (MemoryStream ms = new MemoryStream())
- {
- stream.CopyTo(ms);
- ms.Position = 0;
-
- if (this.Decode(ms, options))
- {
- return;
- }
- }
- }
-
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.AppendLine("Image cannot be loaded. Available formats:");
-
- foreach (IImageFormat format in this.Configuration.ImageFormats)
- {
- stringBuilder.AppendLine("-" + format);
- }
-
- throw new NotSupportedException(stringBuilder.ToString());
- }
-
- ///
- /// Decodes the image stream to the current image.
- ///
- /// The stream.
- /// The options for the decoder.
- ///
- /// The .
- ///
- private bool Decode(Stream stream, IDecoderOptions options)
- {
- int maxHeaderSize = this.Configuration.MaxHeaderSize;
- if (maxHeaderSize <= 0)
- {
- return false;
- }
-
- IImageFormat format;
- byte[] header = ArrayPool.Shared.Rent(maxHeaderSize);
- try
- {
- long startPosition = stream.Position;
- stream.Read(header, 0, maxHeaderSize);
- stream.Position = startPosition;
- format = this.Configuration.ImageFormats.FirstOrDefault(x => x.IsSupportedFileFormat(header));
- }
- finally
- {
- ArrayPool.Shared.Return(header);
- }
-
- if (format == null)
- {
- return false;
- }
-
- format.Decoder.Decode(this, stream, options);
- this.CurrentImageFormat = format;
- return true;
- }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs
index de1e42476..d7d5e88b5 100644
--- a/src/ImageSharp/MetaData/ImageMetaData.cs
+++ b/src/ImageSharp/MetaData/ImageMetaData.cs
@@ -5,6 +5,7 @@
namespace ImageSharp
{
+ using System;
using System.Collections.Generic;
///
@@ -47,21 +48,7 @@ namespace ImageSharp
{
DebugGuard.NotNull(other, nameof(other));
- this.HorizontalResolution = other.HorizontalResolution;
- this.VerticalResolution = other.VerticalResolution;
- this.Quality = other.Quality;
- this.FrameDelay = other.FrameDelay;
- this.RepeatCount = other.RepeatCount;
-
- foreach (ImageProperty property in other.Properties)
- {
- this.Properties.Add(new ImageProperty(property));
- }
-
- if (other.ExifProfile != null)
- {
- this.ExifProfile = new ExifProfile(other.ExifProfile);
- }
+ this.LoadFrom(other);
}
///
@@ -143,5 +130,32 @@ namespace ImageSharp
{
this.ExifProfile?.Sync(this);
}
+
+ ///
+ /// Sets the current metadata values based on a previous metadata object.
+ ///
+ /// Meta data object to copy values from.
+ internal void LoadFrom(ImageMetaData other)
+ {
+ this.HorizontalResolution = other.HorizontalResolution;
+ this.VerticalResolution = other.VerticalResolution;
+ this.Quality = other.Quality;
+ this.FrameDelay = other.FrameDelay;
+ this.RepeatCount = other.RepeatCount;
+
+ foreach (ImageProperty property in other.Properties)
+ {
+ this.Properties.Add(new ImageProperty(property));
+ }
+
+ if (other.ExifProfile != null)
+ {
+ this.ExifProfile = new ExifProfile(other.ExifProfile);
+ }
+ else
+ {
+ this.ExifProfile = null;
+ }
+ }
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
index b363286b0..c4a94c5ff 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
@@ -137,7 +137,7 @@ namespace ImageSharp
using (MemoryStream memStream = new MemoryStream(this.data, this.thumbnailOffset, this.thumbnailLength))
{
- return new Image(memStream);
+ return Image.Load(memStream);
}
}
diff --git a/tests/ImageSharp.Benchmarks/Image/DecodeBmp.cs b/tests/ImageSharp.Benchmarks/Image/DecodeBmp.cs
index 431bbeb07..acde8e0db 100644
--- a/tests/ImageSharp.Benchmarks/Image/DecodeBmp.cs
+++ b/tests/ImageSharp.Benchmarks/Image/DecodeBmp.cs
@@ -43,7 +43,7 @@ namespace ImageSharp.Benchmarks.Image
{
using (MemoryStream memoryStream = new MemoryStream(this.bmpBytes))
{
- using (CoreImage image = new CoreImage(memoryStream))
+ using (CoreImage image = CoreImage.Load(memoryStream))
{
return new CoreSize(image.Width, image.Height);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/DecodeFilteredPng.cs b/tests/ImageSharp.Benchmarks/Image/DecodeFilteredPng.cs
index 517915bac..6786cfdc0 100644
--- a/tests/ImageSharp.Benchmarks/Image/DecodeFilteredPng.cs
+++ b/tests/ImageSharp.Benchmarks/Image/DecodeFilteredPng.cs
@@ -31,7 +31,7 @@ namespace ImageSharp.Benchmarks.Image
private Size LoadPng(MemoryStream stream)
{
- using (Image image = new Image(stream))
+ using (Image image = Image.Load(stream))
{
return new Size(image.Width, image.Height);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/DecodeGif.cs b/tests/ImageSharp.Benchmarks/Image/DecodeGif.cs
index cb70213da..a9bb4c7b3 100644
--- a/tests/ImageSharp.Benchmarks/Image/DecodeGif.cs
+++ b/tests/ImageSharp.Benchmarks/Image/DecodeGif.cs
@@ -43,7 +43,7 @@ namespace ImageSharp.Benchmarks.Image
{
using (MemoryStream memoryStream = new MemoryStream(this.gifBytes))
{
- using (CoreImage image = new CoreImage(memoryStream))
+ using (CoreImage image = CoreImage.Load(memoryStream))
{
return new CoreSize(image.Width, image.Height);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs b/tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs
index cbbe9c9f2..6ce230370 100644
--- a/tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs
+++ b/tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs
@@ -43,7 +43,7 @@ namespace ImageSharp.Benchmarks.Image
{
using (MemoryStream memoryStream = new MemoryStream(this.jpegBytes))
{
- using (CoreImage image = new CoreImage(memoryStream))
+ using (CoreImage image = CoreImage.Load(memoryStream))
{
return new CoreSize(image.Width, image.Height);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/DecodeJpegMultiple.cs b/tests/ImageSharp.Benchmarks/Image/DecodeJpegMultiple.cs
index c79d61538..5c3c1e115 100644
--- a/tests/ImageSharp.Benchmarks/Image/DecodeJpegMultiple.cs
+++ b/tests/ImageSharp.Benchmarks/Image/DecodeJpegMultiple.cs
@@ -25,7 +25,7 @@ namespace ImageSharp.Benchmarks.Image
public void DecodeJpegImageSharp()
{
this.ForEachStream(
- ms => new ImageSharp.Image(ms)
+ ms => ImageSharp.Image.Load(ms)
);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/DecodePng.cs b/tests/ImageSharp.Benchmarks/Image/DecodePng.cs
index 79c8dbc23..620a48a3b 100644
--- a/tests/ImageSharp.Benchmarks/Image/DecodePng.cs
+++ b/tests/ImageSharp.Benchmarks/Image/DecodePng.cs
@@ -43,7 +43,7 @@ namespace ImageSharp.Benchmarks.Image
{
using (MemoryStream memoryStream = new MemoryStream(this.pngBytes))
{
- using (CoreImage image = new CoreImage(memoryStream))
+ using (CoreImage image = CoreImage.Load(memoryStream))
{
return new CoreSize(image.Width, image.Height);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/EncodeBmp.cs b/tests/ImageSharp.Benchmarks/Image/EncodeBmp.cs
index b0a3b4499..6ed577338 100644
--- a/tests/ImageSharp.Benchmarks/Image/EncodeBmp.cs
+++ b/tests/ImageSharp.Benchmarks/Image/EncodeBmp.cs
@@ -25,7 +25,7 @@ namespace ImageSharp.Benchmarks.Image
if (this.bmpStream == null)
{
this.bmpStream = File.OpenRead("../ImageSharp.Tests/TestImages/Formats/Bmp/Car.bmp");
- this.bmpCore = new CoreImage(this.bmpStream);
+ this.bmpCore = CoreImage.Load(this.bmpStream);
this.bmpStream.Position = 0;
this.bmpDrawing = Image.FromStream(this.bmpStream);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/EncodeGif.cs b/tests/ImageSharp.Benchmarks/Image/EncodeGif.cs
index 0810f3fe1..fabeba1bd 100644
--- a/tests/ImageSharp.Benchmarks/Image/EncodeGif.cs
+++ b/tests/ImageSharp.Benchmarks/Image/EncodeGif.cs
@@ -25,7 +25,7 @@ namespace ImageSharp.Benchmarks.Image
if (this.bmpStream == null)
{
this.bmpStream = File.OpenRead("../ImageSharp.Tests/TestImages/Formats/Bmp/Car.bmp");
- this.bmpCore = new CoreImage(this.bmpStream);
+ this.bmpCore = CoreImage.Load(this.bmpStream);
this.bmpStream.Position = 0;
this.bmpDrawing = Image.FromStream(this.bmpStream);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/EncodeIndexedPng.cs b/tests/ImageSharp.Benchmarks/Image/EncodeIndexedPng.cs
index ba383873c..1318c1674 100644
--- a/tests/ImageSharp.Benchmarks/Image/EncodeIndexedPng.cs
+++ b/tests/ImageSharp.Benchmarks/Image/EncodeIndexedPng.cs
@@ -34,7 +34,7 @@ namespace ImageSharp.Benchmarks.Image
? "../ImageSharp.Tests/TestImages/Formats/Jpg/baseline/jpeg420exif.jpg"
: "../ImageSharp.Tests/TestImages/Formats/Bmp/Car.bmp";
this.bmpStream = File.OpenRead(path);
- this.bmpCore = new Image(this.bmpStream);
+ this.bmpCore = Image.Load(this.bmpStream);
this.bmpStream.Position = 0;
}
}
diff --git a/tests/ImageSharp.Benchmarks/Image/EncodeJpeg.cs b/tests/ImageSharp.Benchmarks/Image/EncodeJpeg.cs
index f835f9666..7649812ec 100644
--- a/tests/ImageSharp.Benchmarks/Image/EncodeJpeg.cs
+++ b/tests/ImageSharp.Benchmarks/Image/EncodeJpeg.cs
@@ -25,7 +25,7 @@ namespace ImageSharp.Benchmarks.Image
if (this.bmpStream == null)
{
this.bmpStream = File.OpenRead("../ImageSharp.Tests/TestImages/Formats/Bmp/Car.bmp");
- this.bmpCore = new CoreImage(this.bmpStream);
+ this.bmpCore = CoreImage.Load(this.bmpStream);
this.bmpStream.Position = 0;
this.bmpDrawing = Image.FromStream(this.bmpStream);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/EncodePng.cs b/tests/ImageSharp.Benchmarks/Image/EncodePng.cs
index 0bb0e922c..4c1feb6c2 100644
--- a/tests/ImageSharp.Benchmarks/Image/EncodePng.cs
+++ b/tests/ImageSharp.Benchmarks/Image/EncodePng.cs
@@ -38,7 +38,7 @@ namespace ImageSharp.Benchmarks.Image
? "../ImageSharp.Tests/TestImages/Formats/Jpg/baseline/jpeg420exif.jpg"
: "../ImageSharp.Tests/TestImages/Formats/Bmp/Car.bmp";
this.bmpStream = File.OpenRead(path);
- this.bmpCore = new CoreImage(this.bmpStream);
+ this.bmpCore = CoreImage.Load(this.bmpStream);
this.bmpStream.Position = 0;
this.bmpDrawing = Image.FromStream(this.bmpStream);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/MultiImageBenchmarkBase.cs b/tests/ImageSharp.Benchmarks/Image/MultiImageBenchmarkBase.cs
index 4fee634f5..a084ca025 100644
--- a/tests/ImageSharp.Benchmarks/Image/MultiImageBenchmarkBase.cs
+++ b/tests/ImageSharp.Benchmarks/Image/MultiImageBenchmarkBase.cs
@@ -154,7 +154,7 @@ namespace ImageSharp.Benchmarks.Image
using (MemoryStream ms1 = new MemoryStream(bytes))
{
- this.FileNamesToImageSharpImages[fn] = new Image(ms1);
+ this.FileNamesToImageSharpImages[fn] = Image.Load(ms1);
}
diff --git a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs b/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs
index 28bec5124..28661b9d6 100644
--- a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs
+++ b/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs
@@ -23,7 +23,7 @@ namespace ImageSharp.Benchmarks
{
using (FileStream stream = File.OpenRead("../ImageSharp.Tests/TestImages/Formats/Bmp/Car.bmp"))
{
- this.image = new CoreImage(stream);
+ this.image = CoreImage.Load(stream);
}
}
}
diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
index ae795c2ec..1ecd04690 100644
--- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
+++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
@@ -150,7 +150,7 @@ namespace ImageSharp.Tests
serialized = memoryStream.ToArray();
}
- using (Image image2 = new Image(serialized))
+ using (Image image2 = Image.Load(serialized))
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{
image2.Save(output);
diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
index a140b7a3c..897778bc3 100644
--- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
@@ -29,7 +29,7 @@ namespace ImageSharp.Tests
input.Save(memStream, new GifFormat(), options);
memStream.Position = 0;
- using (Image output = new Image(memStream))
+ using (Image output = Image.Load(memStream))
{
Assert.Equal(1, output.MetaData.Properties.Count);
Assert.Equal("Comments", output.MetaData.Properties[0].Name);
@@ -56,7 +56,7 @@ namespace ImageSharp.Tests
input.SaveAsGif(memStream, options);
memStream.Position = 0;
- using (Image output = new Image(memStream))
+ using (Image output = Image.Load(memStream))
{
Assert.Equal(0, output.MetaData.Properties.Count);
}
@@ -77,7 +77,7 @@ namespace ImageSharp.Tests
input.Save(memStream, new GifFormat());
memStream.Position = 0;
- using (Image output = new Image(memStream))
+ using (Image output = Image.Load(memStream))
{
Assert.Equal(1, output.MetaData.Properties.Count);
Assert.Equal("Comments", output.MetaData.Properties[0].Name);
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
index 5723f9b23..416c88a50 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
@@ -89,11 +89,10 @@ namespace ImageSharp.Tests
{
image.Save(ms, new JpegEncoder());
ms.Seek(0, SeekOrigin.Begin);
-
- Image mirror = provider.Factory.CreateImage(1, 1);
+
using (JpegDecoderCore decoder = new JpegDecoderCore(null))
{
- decoder.Decode(mirror, ms, true);
+ Image mirror = decoder.Decode(ms);
Assert.Equal(decoder.ImageWidth, image.Width);
Assert.Equal(decoder.ImageHeight, image.Height);
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs
index c97eb1461..0833cb868 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs
@@ -88,7 +88,7 @@ namespace ImageSharp.Tests
input.Save(memStream, new JpegFormat(), options);
memStream.Position = 0;
- using (Image output = new Image(memStream))
+ using (Image output = Image.Load(memStream))
{
Assert.NotNull(output.MetaData.ExifProfile);
}
@@ -113,7 +113,7 @@ namespace ImageSharp.Tests
input.SaveAsJpeg(memStream, options);
memStream.Position = 0;
- using (Image output = new Image(memStream))
+ using (Image output = Image.Load(memStream))
{
Assert.Null(output.MetaData.ExifProfile);
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs
index 50e678bf0..28a64a765 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs
@@ -50,7 +50,7 @@ namespace ImageSharp.Tests
ExecutionCount,
() =>
{
- Image img = new Image(bytes);
+ Image img = Image.Load(bytes);
},
// ReSharper disable once ExplicitCallerInfoArgument
$"Decode {fileName}");
diff --git a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs
new file mode 100644
index 000000000..2c97ea06f
--- /dev/null
+++ b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs
@@ -0,0 +1,341 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.IO;
+ using System.Linq;
+ using ImageSharp.Formats;
+ using ImageSharp.IO;
+ using Moq;
+ using Xunit;
+
+ ///
+ /// Tests the class.
+ ///
+ public class ImageLoadTests : IDisposable
+ {
+ private readonly Mock fileSystem;
+ private readonly IDecoderOptions decoderOptions;
+ private Image returnImage;
+ private Mock localDecoder;
+ private Mock localFormat;
+ private readonly string FilePath;
+
+ public Configuration LocalConfiguration { get; private set; }
+ public byte[] Marker { get; private set; }
+ public MemoryStream DataStream { get; private set; }
+ public byte[] DecodedData { get; private set; }
+
+ public ImageLoadTests()
+ {
+ this.returnImage = new Image(1, 1);
+
+ this.localDecoder = new Mock();
+ this.localFormat = new Mock();
+ this.localFormat.Setup(x => x.Decoder).Returns(this.localDecoder.Object);
+ this.localFormat.Setup(x => x.Encoder).Returns(new Mock().Object);
+ this.localFormat.Setup(x => x.MimeType).Returns("img/test");
+ this.localFormat.Setup(x => x.Extension).Returns("png");
+ this.localFormat.Setup(x => x.HeaderSize).Returns(1);
+ this.localFormat.Setup(x => x.IsSupportedFileFormat(It.IsAny())).Returns(true);
+ this.localFormat.Setup(x => x.SupportedExtensions).Returns(new string[] { "png", "jpg" });
+ this.localDecoder.Setup(x => x.Decode(It.IsAny(), It.IsAny()))
+ .Callback((s, o) => {
+ using (var ms = new MemoryStream())
+ {
+ s.CopyTo(ms);
+ this.DecodedData = ms.ToArray();
+ }
+ })
+ .Returns(this.returnImage);
+
+ this.fileSystem = new Mock();
+
+ this.LocalConfiguration = new Configuration(this.localFormat.Object)
+ {
+ FileSystem = this.fileSystem.Object
+ };
+ TestFormat.RegisterGloablTestFormat();
+ this.Marker = Guid.NewGuid().ToByteArray();
+ this.DataStream = TestFormat.GlobalTestFormat.CreateStream(this.Marker);
+ this.decoderOptions = new Mock().Object;
+
+ this.FilePath = Guid.NewGuid().ToString();
+ this.fileSystem.Setup(x => x.OpenRead(this.FilePath)).Returns(this.DataStream);
+ }
+
+ [Fact]
+ public void LoadFromStream()
+ {
+ Image img = Image.Load(this.DataStream);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, null);
+ }
+
+ [Fact]
+ public void LoadFromStreamWithType()
+ {
+ Image img = Image.Load(this.DataStream);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, null);
+ }
+
+ [Fact]
+ public void LoadFromStreamWithOptions()
+ {
+ Image img = Image.Load(this.DataStream, this.decoderOptions);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, this.decoderOptions);
+ }
+
+ [Fact]
+ public void LoadFromStreamWithTypeAndOptions()
+ {
+ Image img = Image.Load(this.DataStream, this.decoderOptions);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, this.decoderOptions);
+ }
+
+ [Fact]
+ public void LoadFromStreamWithConfig()
+ {
+ Stream stream = new MemoryStream();
+ Image img = Image.Load(stream, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(stream, null));
+ }
+
+ [Fact]
+ public void LoadFromStreamWithTypeAndConfig()
+ {
+ Stream stream = new MemoryStream();
+ Image img = Image.Load(stream, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(stream, null));
+ }
+
+ [Fact]
+ public void LoadFromStreamWithConfigAndOptions()
+ {
+ Stream stream = new MemoryStream();
+ Image img = Image.Load(stream, this.decoderOptions, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(stream, this.decoderOptions));
+ }
+
+ [Fact]
+ public void LoadFromStreamWithTypeAndConfigAndOptions()
+ {
+ Stream stream = new MemoryStream();
+ Image img = Image.Load(stream, this.decoderOptions, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(stream, this.decoderOptions));
+ }
+
+ [Fact]
+ public void LoadFromBytes()
+ {
+ Image img = Image.Load(this.DataStream.ToArray());
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, null);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithType()
+ {
+ Image img = Image.Load(this.DataStream.ToArray());
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, null);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithOptions()
+ {
+ Image img = Image.Load(this.DataStream.ToArray(), this.decoderOptions);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, this.decoderOptions);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithTypeAndOptions()
+ {
+ Image img = Image.Load(this.DataStream.ToArray(), this.decoderOptions);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, this.decoderOptions);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithConfig()
+ {
+ Image img = Image.Load(this.DataStream.ToArray(), this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(It.IsAny(), null));
+ Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithTypeAndConfig()
+ {
+ Image img = Image.Load(this.DataStream.ToArray(), this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+
+ this.localDecoder.Verify(x => x.Decode(It.IsAny(), null));
+ Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithConfigAndOptions()
+ {
+ Image img = Image.Load(this.DataStream.ToArray(), this.decoderOptions, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(It.IsAny(), this.decoderOptions));
+ Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithTypeAndConfigAndOptions()
+ {
+ Image img = Image.Load(this.DataStream.ToArray(), this.decoderOptions, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(It.IsAny(), this.decoderOptions));
+ Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
+ }
+
+ [Fact]
+ public void LoadFromFile()
+ {
+ Image img = Image.Load(this.DataStream);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, null);
+ }
+
+ [Fact]
+ public void LoadFromFileWithType()
+ {
+ Image img = Image.Load(this.DataStream);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, null);
+ }
+
+ [Fact]
+ public void LoadFromFileWithOptions()
+ {
+ Image img = Image.Load(this.DataStream, this.decoderOptions);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, this.decoderOptions);
+ }
+
+ [Fact]
+ public void LoadFromFileWithTypeAndOptions()
+ {
+ Image img = Image.Load(this.DataStream, this.decoderOptions);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
+ Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, this.decoderOptions);
+ }
+
+ [Fact]
+ public void LoadFromFileWithConfig()
+ {
+ Image img = Image.Load(this.FilePath, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(this.DataStream, null));
+ }
+
+ [Fact]
+ public void LoadFromFileWithTypeAndConfig()
+ {
+ Image img = Image.Load(this.FilePath, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(this.DataStream, null));
+ }
+
+ [Fact]
+ public void LoadFromFileWithConfigAndOptions()
+ {
+ Image img = Image.Load(this.FilePath, this.decoderOptions, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(this.DataStream, this.decoderOptions));
+ }
+
+ [Fact]
+ public void LoadFromFileWithTypeAndConfigAndOptions()
+ {
+ Image img = Image.Load(FilePath, this.decoderOptions, this.LocalConfiguration);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+ Assert.Equal(this.localFormat.Object, img.CurrentImageFormat);
+ this.localDecoder.Verify(x => x.Decode(this.DataStream, this.decoderOptions));
+ }
+
+ public void Dispose()
+ {
+ // clean up the global object;
+ this.returnImage?.Dispose();
+ }
+ }
+}
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.cs b/tests/ImageSharp.Tests/Image/ImageTests.cs
index b0a031a78..02b0e5ad9 100644
--- a/tests/ImageSharp.Tests/Image/ImageTests.cs
+++ b/tests/ImageSharp.Tests/Image/ImageTests.cs
@@ -21,11 +21,11 @@ namespace ImageSharp.Tests
{
Assert.Throws(() =>
{
- new Image((byte[])null);
+ Image.Load((byte[])null);
});
TestFile file = TestFile.Create(TestImages.Bmp.Car);
- using (Image image = new Image(file.Bytes))
+ using (Image image = Image.Load(file.Bytes))
{
Assert.Equal(600, image.Width);
Assert.Equal(450, image.Height);
@@ -36,7 +36,7 @@ namespace ImageSharp.Tests
public void ConstructorFileSystem()
{
TestFile file = TestFile.Create(TestImages.Bmp.Car);
- using (Image image = new Image(file.FilePath))
+ using (Image image = Image.Load(file.FilePath))
{
Assert.Equal(600, image.Width);
Assert.Equal(450, image.Height);
@@ -49,7 +49,7 @@ namespace ImageSharp.Tests
System.IO.FileNotFoundException ex = Assert.Throws(
() =>
{
- new Image(Guid.NewGuid().ToString());
+ Image.Load(Guid.NewGuid().ToString());
});
}
@@ -59,7 +59,7 @@ namespace ImageSharp.Tests
ArgumentNullException ex = Assert.Throws(
() =>
{
- new Image((string) null);
+ Image.Load((string) null);
});
}
diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
index 785d9dcfc..1bc31286d 100644
--- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
@@ -73,7 +73,7 @@ namespace ImageSharp.Tests
image.SaveAsJpeg(memStream);
memStream.Position = 0;
- image = new Image(memStream);
+ image = Image.Load(memStream);
profile = image.MetaData.ExifProfile;
Assert.NotNull(profile);
@@ -91,7 +91,7 @@ namespace ImageSharp.Tests
image.SaveAsJpeg(memStream);
memStream.Position = 0;
- image = new Image(memStream);
+ image = Image.Load(memStream);
profile = image.MetaData.ExifProfile;
Assert.NotNull(profile);
@@ -286,7 +286,7 @@ namespace ImageSharp.Tests
image.Dispose();
memStream.Position = 0;
- return new Image(memStream);
+ return Image.Load(memStream);
}
}
diff --git a/tests/ImageSharp.Tests/TestFile.cs b/tests/ImageSharp.Tests/TestFile.cs
index 701025e87..eedc0d306 100644
--- a/tests/ImageSharp.Tests/TestFile.cs
+++ b/tests/ImageSharp.Tests/TestFile.cs
@@ -46,7 +46,7 @@ namespace ImageSharp.Tests
this.file = file;
this.Bytes = File.ReadAllBytes(file);
- this.image = new Image(this.Bytes);
+ this.image = Image.Load(this.Bytes);
}
///
@@ -139,7 +139,7 @@ namespace ImageSharp.Tests
///
public Image CreateImage(IDecoderOptions options)
{
- return new Image(this.Bytes, options);
+ return Image.Load(this.Bytes, options);
}
///
diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs
new file mode 100644
index 000000000..3a40ed420
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestFormat.cs
@@ -0,0 +1,174 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.Collections.Concurrent;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Reflection;
+ using ImageSharp.Formats;
+ using Xunit;
+
+ ///
+ /// A test image file.
+ ///
+ public class TestFormat : ImageSharp.Formats.IImageFormat
+ {
+ public static TestFormat GlobalTestFormat { get; } = new TestFormat();
+
+ public static void RegisterGloablTestFormat()
+ {
+ Configuration.Default.AddImageFormat(GlobalTestFormat);
+ }
+
+ public TestFormat()
+ {
+ this.Encoder = new TestEncoder(this); ;
+ this.Decoder = new TestDecoder(this); ;
+ }
+
+ public List DecodeCalls { get; } = new List();
+
+ public IImageEncoder Encoder { get; }
+
+ public IImageDecoder Decoder { get; }
+
+ private byte[] header = Guid.NewGuid().ToByteArray();
+
+ public MemoryStream CreateStream(byte[] marker = null)
+ {
+ MemoryStream ms = new MemoryStream();
+ byte[] data = this.header;
+ ms.Write(data, 0, data.Length);
+ if (marker != null)
+ {
+ ms.Write(marker, 0, marker.Length);
+ }
+ ms.Position = 0;
+ return ms;
+ }
+
+ Dictionary _sampleImages = new Dictionary();
+
+ public void VerifyDecodeCall(byte[] marker, IDecoderOptions options)
+ {
+ DecodeOperation[] discovered = this.DecodeCalls.Where(x => x.IsMatch(marker, options)).ToArray();
+
+ Assert.True(discovered.Any(), "No calls to decode on this formate with the proveded options happend");
+
+ foreach (DecodeOperation d in discovered) {
+ this.DecodeCalls.Remove(d);
+ }
+ }
+
+ public Image Sample()
+ where TColor : struct, IPixel
+ {
+ lock (this._sampleImages)
+ {
+ if (!this._sampleImages.ContainsKey(typeof(TColor)))
+ {
+ this._sampleImages.Add(typeof(TColor), new Image(1, 1));
+ }
+
+ return (Image)this._sampleImages[typeof(TColor)];
+ }
+ }
+
+ public string MimeType => "img/test";
+
+ public string Extension => "test_ext";
+
+ public IEnumerable SupportedExtensions => new[] { "test_ext" };
+
+ public int HeaderSize => this.header.Length;
+
+ public bool IsSupportedFileFormat(byte[] header)
+ {
+ if (header.Length < this.header.Length)
+ {
+ return false;
+ }
+ for (int i = 0; i < this.header.Length; i++)
+ {
+ if (header[i] != this.header[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ public struct DecodeOperation
+ {
+ public byte[] marker;
+ public IDecoderOptions options;
+
+ public bool IsMatch(byte[] testMarker, IDecoderOptions testOptions)
+ {
+ if(this.options != testOptions)
+ {
+ return false;
+ }
+
+ if (testMarker.Length != this.marker.Length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < this.marker.Length; i++)
+ {
+ if (testMarker[i] != this.marker[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ public class TestDecoder : ImageSharp.Formats.IImageDecoder
+ {
+ private TestFormat testFormat;
+
+ public TestDecoder(TestFormat testFormat)
+ {
+ this.testFormat = testFormat;
+ }
+
+ public Image Decode(Stream stream, IDecoderOptions options) where TColor : struct, IPixel
+ {
+ var ms = new MemoryStream();
+ stream.CopyTo(ms);
+ var marker = ms.ToArray().Skip(this.testFormat.header.Length).ToArray();
+ this.testFormat.DecodeCalls.Add(new DecodeOperation
+ {
+ marker = marker,
+ options = options
+ });
+
+ // TODO record this happend so we an verify it.
+ return this.testFormat.Sample();
+ }
+ }
+
+ public class TestEncoder : ImageSharp.Formats.IImageEncoder
+ {
+ private TestFormat testFormat;
+
+ public TestEncoder(TestFormat testFormat)
+ {
+ this.testFormat = testFormat;
+ }
+
+ public void Encode(Image image, Stream stream, IEncoderOptions options) where TColor : struct, IPixel
+ {
+ // TODO record this happend so we an verify it.
+ }
+ }
+ }
+}
diff --git a/tests/ImageSharp.Tests/TestUtilities/Factories/GenericFactory.cs b/tests/ImageSharp.Tests/TestUtilities/Factories/GenericFactory.cs
index 87b7ace6a..c2fe0dc5c 100644
--- a/tests/ImageSharp.Tests/TestUtilities/Factories/GenericFactory.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/Factories/GenericFactory.cs
@@ -21,7 +21,7 @@ namespace ImageSharp.Tests
public virtual Image CreateImage(byte[] bytes)
{
- return new Image(bytes);
+ return Image.Load(bytes);
}
public virtual Image CreateImage(Image other)
diff --git a/tests/ImageSharp.Tests/TestUtilities/Factories/ImageFactory.cs b/tests/ImageSharp.Tests/TestUtilities/Factories/ImageFactory.cs
index a8d398c1e..2361bc01c 100644
--- a/tests/ImageSharp.Tests/TestUtilities/Factories/ImageFactory.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/Factories/ImageFactory.cs
@@ -7,7 +7,7 @@ namespace ImageSharp.Tests
{
public class ImageFactory : GenericFactory
{
- public override Image CreateImage(byte[] bytes) => new Image(bytes);
+ public override Image CreateImage(byte[] bytes) => Image.Load(bytes);
public override Image CreateImage(int width, int height) => new Image(width, height);