diff --git a/src/ImageSharp/Image/Image.LoadPixelData.cs b/src/ImageSharp/Image/Image.LoadPixelData.cs new file mode 100644 index 0000000000..75aa318bed --- /dev/null +++ b/src/ImageSharp/Image/Image.LoadPixelData.cs @@ -0,0 +1,80 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using System.IO; + using System.Runtime.CompilerServices; + using System.Threading.Tasks; + using Formats; + using ImageSharp.Memory; + using ImageSharp.PixelFormats; + + /// + /// Adds static methods allowing the creation of new image from raw pixel data. + /// + public static partial class Image + { + /// + /// Create a new instance of the class from the raw data. + /// + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + public static Image LoadPixelData(Span data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(Configuration.Default, data, width, height); + + /// + /// Create a new instance of the class from the given byte array in format. + /// + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + public static Image LoadPixelData(Span data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(Configuration.Default, data, width, height); + + /// + /// Create a new instance of the class from the given byte array in format. + /// + /// The config for the decoder. + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + public static Image LoadPixelData(Configuration config, Span data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(config, data.NonPortableCast(), width, height); + + /// + /// Create a new instance of the class from the raw data. + /// + /// The config for the decoder. + /// The Span containing the image Pixel data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + public static Image LoadPixelData(Configuration config, Span data, int width, int height) + where TPixel : struct, IPixel + { + int count = width * height; + Guard.MustBeGreaterThanOrEqualTo(data.Length, width * height, nameof(data)); + var image = new Image(config, width, height); + var dest = new Span(image.Pixels, 0, count); + + SpanHelper.Copy(data, dest, count); + + return image; + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs index 4cdf529e6d..7a5b8ffc53 100644 --- a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs @@ -526,6 +526,48 @@ namespace ImageSharp.Tests this.localDecoder.Verify(x => x.Decode(Configuration.Default, this.DataStream, this.decoderOptions)); } + [Fact] + public void LoadFromPixelData_Pixels() + { + var img = Image.LoadPixelData(new Rgba32[] { + Rgba32.Black, Rgba32.White, + Rgba32.White, Rgba32.Black, + }, 2, 2); + + Assert.NotNull(img); + using (var px = img.Lock()) + { + Assert.Equal(Rgba32.Black, px[0, 0]); + Assert.Equal(Rgba32.White, px[0, 1]); + + Assert.Equal(Rgba32.White, px[1, 0]); + Assert.Equal(Rgba32.Black, px[1, 1]); + + } + } + + [Fact] + public void LoadFromPixelData_Bytes() + { + var img = Image.LoadPixelData(new byte[] { + 0,0,0,255, // 0,0 + 255,255,255,255, // 0,1 + 255,255,255,255, // 1,0 + 0,0,0,255, // 1,1 + }, 2, 2); + + Assert.NotNull(img); + using (var px = img.Lock()) + { + Assert.Equal(Rgba32.Black, px[0, 0]); + Assert.Equal(Rgba32.White, px[0, 1]); + + Assert.Equal(Rgba32.White, px[1, 0]); + Assert.Equal(Rgba32.Black, px[1, 1]); + + } + } + public void Dispose() { // clean up the global object;