diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index af31eff792..8bfd8ee1a3 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -223,17 +223,5 @@ namespace ImageSharp : base(other) { } - - /// - public override PixelAccessor Lock() - { - return new PixelAccessor(this); - } - - /// - internal override ImageFrame ToFrame() - { - return new ImageFrame(this); - } } } diff --git a/src/ImageSharp/Image/ImageBase{TColor}.cs b/src/ImageSharp/Image/ImageBase{TColor}.cs index 2badc008a2..830318b32b 100644 --- a/src/ImageSharp/Image/ImageBase{TColor}.cs +++ b/src/ImageSharp/Image/ImageBase{TColor}.cs @@ -150,7 +150,7 @@ namespace ImageSharp } /// - public virtual PixelAccessor Lock() + public PixelAccessor Lock() { return new PixelAccessor(this); } diff --git a/src/ImageSharp/Image/PixelAccessor{TColor}.cs b/src/ImageSharp/Image/PixelAccessor{TColor}.cs index e104b8ae77..a106765652 100644 --- a/src/ImageSharp/Image/PixelAccessor{TColor}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TColor}.cs @@ -15,7 +15,7 @@ namespace ImageSharp /// Provides per-pixel access to generic pixels. /// /// The pixel format. - public unsafe class PixelAccessor : IDisposable + public sealed unsafe class PixelAccessor : IDisposable where TColor : struct, IPixel { /// @@ -91,7 +91,7 @@ namespace ImageSharp /// /// Gets the pixel buffer array. /// - public TColor[] PixelBuffer => this.pixelBuffer.Array; + public TColor[] PixelArray => this.pixelBuffer.Array; /// /// Gets the pointer to the pixel buffer. @@ -123,6 +123,8 @@ namespace ImageSharp /// public ParallelOptions ParallelOptions { get; } + private static BulkPixelOperations Operations => BulkPixelOperations.Instance; + /// /// Gets or sets the pixel at the specified position. /// @@ -236,6 +238,17 @@ namespace ImageSharp Unsafe.InitBlock(this.pixelsBase, 0, (uint)(this.RowStride * this.Height)); } + /// + /// Gets a to the row 'y' beginning from the pixel at 'x'. + /// + /// The x coordinate + /// The y coordinate + /// The + internal BufferPointer GetRowPointer(int x, int y) + { + return this.pixelBuffer.Slice((y * this.Width) + x); + } + /// /// Sets the pixel buffer in an unsafe manner. This should not be used unless you know what its doing!!! /// @@ -270,24 +283,15 @@ namespace ImageSharp /// The target row index. /// The width. /// The height. - protected virtual void CopyFromZyx(PixelArea area, int targetX, int targetY, int width, int height) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CopyFromZyx(PixelArea area, int targetX, int targetY, int width, int height) { - TColor packed = default(TColor); - int size = Unsafe.SizeOf(); - for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowStride); - byte* destination = this.GetRowPointer(targetX, targetY + y); - - for (int x = 0; x < width; x++) - { - packed.PackFromBytes(*(source + 2), *(source + 1), *source, 255); - Unsafe.Write(destination, packed); + BufferPointer source = area.GetRowPointer(y); + BufferPointer destination = this.GetRowPointer(targetX, targetY + y); - source += 3; - destination += size; - } + Operations.PackFromZyxBytes(source, destination, width); } } @@ -299,24 +303,15 @@ namespace ImageSharp /// The target row index. /// The width. /// The height. - protected virtual void CopyFromZyxw(PixelArea area, int targetX, int targetY, int width, int height) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CopyFromZyxw(PixelArea area, int targetX, int targetY, int width, int height) { - TColor packed = default(TColor); - int size = Unsafe.SizeOf(); - for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowStride); - byte* destination = this.GetRowPointer(targetX, targetY + y); - - for (int x = 0; x < width; x++) - { - packed.PackFromBytes(*(source + 2), *(source + 1), *source, *(source + 3)); - Unsafe.Write(destination, packed); + BufferPointer source = area.GetRowPointer(y); + BufferPointer destination = this.GetRowPointer(targetX, targetY + y); - source += 4; - destination += size; - } + Operations.PackFromZyxwBytes(source, destination, width); } } @@ -328,24 +323,15 @@ namespace ImageSharp /// The target row index. /// The width. /// The height. - protected virtual void CopyFromXyz(PixelArea area, int targetX, int targetY, int width, int height) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CopyFromXyz(PixelArea area, int targetX, int targetY, int width, int height) { - TColor packed = default(TColor); - int size = Unsafe.SizeOf(); - for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowStride); - byte* destination = this.GetRowPointer(targetX, targetY + y); - - for (int x = 0; x < width; x++) - { - packed.PackFromBytes(*source, *(source + 1), *(source + 2), 255); - Unsafe.Write(destination, packed); + BufferPointer source = area.GetRowPointer(y); + BufferPointer destination = this.GetRowPointer(targetX, targetY + y); - source += 3; - destination += size; - } + Operations.PackFromXyzBytes(source, destination, width); } } @@ -357,24 +343,14 @@ namespace ImageSharp /// The target row index. /// The width. /// The height. - protected virtual void CopyFromXyzw(PixelArea area, int targetX, int targetY, int width, int height) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CopyFromXyzw(PixelArea area, int targetX, int targetY, int width, int height) { - TColor packed = default(TColor); - int size = Unsafe.SizeOf(); - for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowStride); - byte* destination = this.GetRowPointer(targetX, targetY + y); - - for (int x = 0; x < width; x++) - { - packed.PackFromBytes(*source, *(source + 1), *(source + 2), *(source + 3)); - Unsafe.Write(destination, packed); - - source += 4; - destination += size; - } + BufferPointer source = area.GetRowPointer(y); + BufferPointer destination = this.GetRowPointer(targetX, targetY + y); + Operations.PackFromXyzwBytes(source, destination, width); } } @@ -386,16 +362,14 @@ namespace ImageSharp /// The source row index. /// The width. /// The height. - protected virtual void CopyToZyx(PixelArea area, int sourceX, int sourceY, int width, int height) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CopyToZyx(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { - int offset = y * area.RowStride; - for (int x = 0; x < width; x++) - { - this[sourceX + x, sourceY + y].ToZyxBytes(area.Bytes, offset); - offset += 3; - } + BufferPointer source = this.GetRowPointer(sourceX, sourceY + y); + BufferPointer destination = area.GetRowPointer(y); + Operations.ToZyxBytes(source, destination, width); } } @@ -407,16 +381,14 @@ namespace ImageSharp /// The source row index. /// The width. /// The height. - protected virtual void CopyToZyxw(PixelArea area, int sourceX, int sourceY, int width, int height) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CopyToZyxw(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { - int offset = y * area.RowStride; - for (int x = 0; x < width; x++) - { - this[sourceX + x, sourceY + y].ToZyxwBytes(area.Bytes, offset); - offset += 4; - } + BufferPointer source = this.GetRowPointer(sourceX, sourceY + y); + BufferPointer destination = area.GetRowPointer(y); + Operations.ToZyxwBytes(source, destination, width); } } @@ -428,16 +400,14 @@ namespace ImageSharp /// The source row index. /// The width. /// The height. - protected virtual void CopyToXyz(PixelArea area, int sourceX, int sourceY, int width, int height) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CopyToXyz(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { - int offset = y * area.RowStride; - for (int x = 0; x < width; x++) - { - this[sourceX + x, sourceY + y].ToXyzBytes(area.Bytes, offset); - offset += 3; - } + BufferPointer source = this.GetRowPointer(sourceX, sourceY + y); + BufferPointer destination = area.GetRowPointer(y); + Operations.ToXyzBytes(source, destination, width); } } @@ -449,32 +419,17 @@ namespace ImageSharp /// The source row index. /// The width. /// The height. - protected virtual void CopyToXyzw(PixelArea area, int sourceX, int sourceY, int width, int height) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void CopyToXyzw(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { - int offset = y * area.RowStride; - for (int x = 0; x < width; x++) - { - this[sourceX + x, sourceY + y].ToXyzwBytes(area.Bytes, offset); - offset += 4; - } + BufferPointer source = this.GetRowPointer(sourceX, sourceY + y); + BufferPointer destination = area.GetRowPointer(y); + Operations.ToXyzwBytes(source, destination, width); } } - /// - /// Gets the pointer at the specified row. - /// - /// The column index. - /// The row index. - /// - /// The . - /// - protected byte* GetRowPointer(int x, int y) - { - return this.pixelsBase + (((y * this.Width) + x) * Unsafe.SizeOf()); - } - private void SetPixelBufferUnsafe(int width, int height, TColor[] pixels) { this.SetPixelBufferUnsafe(width, height, new PinnedBuffer(width * height, pixels)); diff --git a/src/ImageSharp/Image/PixelArea{TColor}.cs b/src/ImageSharp/Image/PixelArea{TColor}.cs index c54de12d6c..be6debba2f 100644 --- a/src/ImageSharp/Image/PixelArea{TColor}.cs +++ b/src/ImageSharp/Image/PixelArea{TColor}.cs @@ -203,6 +203,16 @@ namespace ImageSharp Unsafe.InitBlock(this.PixelBase, 0, (uint)(this.RowStride * this.Height)); } + /// + /// Gets a to the row y. + /// + /// The y coordinate + /// The + internal BufferPointer GetRowPointer(int y) + { + return this.byteBuffer.Slice(y * this.RowStride); + } + /// /// Gets component count for the given order. /// diff --git a/src/ImageSharp/ImageFrame.cs b/src/ImageSharp/ImageFrame.cs deleted file mode 100644 index be654111df..0000000000 --- a/src/ImageSharp/ImageFrame.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System.Diagnostics; - - /// - /// An optimized frame for the class. - /// - [DebuggerDisplay("ImageFrame: {Width}x{Height}")] - public sealed class ImageFrame : ImageFrame - { - /// - /// Initializes a new instance of the class. - /// - /// The width of the image in pixels. - /// The height of the image in pixels. - /// - /// The configuration providing initialization code which allows extending the library. - /// - public ImageFrame(int width, int height, Configuration configuration = null) - : base(width, height, configuration) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The image to create the frame from. - /// - public ImageFrame(ImageBase image) - : base(image) - { - } - - /// - public override PixelAccessor Lock() - { - return new PixelAccessor(this); - } - - /// - internal override ImageFrame Clone() - { - return new ImageFrame(this); - } - } -} diff --git a/src/ImageSharp/PixelAccessor.cs b/src/ImageSharp/PixelAccessor.cs deleted file mode 100644 index 7827e7b47b..0000000000 --- a/src/ImageSharp/PixelAccessor.cs +++ /dev/null @@ -1,153 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System.Runtime.CompilerServices; - - /// - /// An optimized pixel accessor for the class. - /// - public sealed unsafe class PixelAccessor : PixelAccessor - { - /// - /// Initializes a new instance of the class. - /// - /// The image to provide pixel access for. - public PixelAccessor(ImageBase image) - : base(image) - { - } - - /// - protected override void CopyFromXyzw(PixelArea area, int targetX, int targetY, int width, int height) - { - uint byteCount = (uint)width * 4; - - for (int y = 0; y < height; y++) - { - byte* source = area.PixelBase + (y * area.RowStride); - byte* destination = this.GetRowPointer(targetX, targetY + y); - - Unsafe.CopyBlock(destination, source, byteCount); - } - } - - /// - protected override void CopyFromXyz(PixelArea area, int targetX, int targetY, int width, int height) - { - for (int y = 0; y < height; y++) - { - byte* source = area.PixelBase + (y * area.RowStride); - byte* destination = this.GetRowPointer(targetX, targetY + y); - - for (int x = 0; x < width; x++) - { - Unsafe.Write(destination, (uint)(*source << 0 | *(source + 1) << 8 | *(source + 2) << 16 | 255 << 24)); - - source += 3; - destination += 4; - } - } - } - - /// - protected override void CopyFromZyx(PixelArea area, int targetX, int targetY, int width, int height) - { - for (int y = 0; y < height; y++) - { - byte* source = area.PixelBase + (y * area.RowStride); - byte* destination = this.GetRowPointer(targetX, targetY + y); - - for (int x = 0; x < width; x++) - { - Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | 255 << 24)); - - source += 3; - destination += 4; - } - } - } - - /// - protected override void CopyFromZyxw(PixelArea area, int targetX, int targetY, int width, int height) - { - for (int y = 0; y < height; y++) - { - byte* source = area.PixelBase + (y * area.RowStride); - byte* destination = this.GetRowPointer(targetX, targetY + y); - - for (int x = 0; x < width; x++) - { - Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | *(source + 3) << 24)); - - source += 4; - destination += 4; - } - } - } - - /// - protected override void CopyToZyx(PixelArea area, int sourceX, int sourceY, int width, int height) - { - for (int y = 0; y < height; y++) - { - byte* source = this.GetRowPointer(sourceX, sourceY + y); - byte* destination = area.PixelBase + (y * area.RowStride); - - for (int x = 0; x < width; x++) - { - *destination = *(source + 2); - *(destination + 1) = *(source + 1); - *(destination + 2) = *(source + 0); - - source += 4; - destination += 3; - } - } - } - - /// - protected override void CopyToXyz(PixelArea area, int sourceX, int sourceY, int width, int height) - { - for (int y = 0; y < height; y++) - { - byte* source = this.GetRowPointer(sourceX, sourceY + y); - byte* destination = area.PixelBase + (y * area.RowStride); - - for (int x = 0; x < width; x++) - { - *destination = *(source + 0); - *(destination + 1) = *(source + 1); - *(destination + 2) = *(source + 2); - - source += 4; - destination += 3; - } - } - } - - /// - protected override void CopyToZyxw(PixelArea area, int sourceX, int sourceY, int width, int height) - { - for (int y = 0; y < height; y++) - { - byte* source = this.GetRowPointer(sourceX, sourceY + y); - byte* destination = area.PixelBase + (y * area.RowStride); - - for (int x = 0; x < width; x++) - { - *destination = *(source + 2); - *(destination + 1) = *(source + 1); - *(destination + 2) = *(source + 0); - *(destination + 3) = *(source + 3); - - source += 4; - destination += 4; - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/PixelAccessorVirtualCopy.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/PixelAccessorVirtualCopy.cs index 694a26f3dd..3df688972f 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/PixelAccessorVirtualCopy.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/PixelAccessorVirtualCopy.cs @@ -114,7 +114,7 @@ namespace ImageSharp.Benchmarks.Color.Bulk private BufferPointer GetPixelAccessorRow(int x, int y) { return new BufferPointer( - this.pixelAccessor.PixelBuffer, + this.pixelAccessor.PixelArray, (void*)this.pixelAccessor.DataPointer, (y * this.pixelAccessor.Width) + x ); diff --git a/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs b/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs index f3cd20f45c..cd9cd04b72 100644 --- a/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs +++ b/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs @@ -130,16 +130,7 @@ namespace ImageSharp.Tests CopyFromZYX(image); } } - - [Fact] - public void CopyFromZYXOptimized() - { - using (Image image = new Image(1, 1)) - { - CopyFromZYX(image); - } - } - + [Fact] public void CopyFromZYXW() { @@ -148,16 +139,7 @@ namespace ImageSharp.Tests CopyFromZYXW(image); } } - - [Fact] - public void CopyFromZYXWOptimized() - { - using (Image image = new Image(1, 1)) - { - CopyFromZYXW(image); - } - } - + [Fact] public void CopyToZYX() { @@ -166,16 +148,7 @@ namespace ImageSharp.Tests CopyToZYX(image); } } - - [Fact] - public void CopyToZYXOptimized() - { - using (Image image = new Image(1, 1)) - { - CopyToZYX(image); - } - } - + [Fact] public void CopyToZYXW() { @@ -184,16 +157,7 @@ namespace ImageSharp.Tests CopyToZYXW(image); } } - - [Fact] - public void CopyToZYXWOptimized() - { - using (Image image = new Image(1, 1)) - { - CopyToZYXW(image); - } - } - + private static void CopyFromZYX(Image image) where TColor : struct, IPixel {