mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: e8d174508130e99cb9152e3c6dad690232425075 Former-commit-id: 4191408f0e2678dfb6937918c46a0d588da073d7 Former-commit-id: 3dc34dfac9b7e02f3dca4e80b1d8cf41fe40ee35af/merge-core
3 changed files with 177 additions and 4 deletions
@ -0,0 +1,25 @@ |
|||
namespace GenericImage |
|||
{ |
|||
using GenericImage.PackedVectors; |
|||
|
|||
public class ImageRgba32 : IImageBase<Rgba32> |
|||
{ |
|||
public ImageRgba32(int width, int height) |
|||
{ |
|||
this.Width = width; |
|||
this.Height = height; |
|||
this.Pixels = new Rgba32[width * height]; |
|||
} |
|||
|
|||
public Rgba32[] Pixels { get; } |
|||
|
|||
public int Width { get; } |
|||
|
|||
public int Height { get; } |
|||
|
|||
public IPixelAccessor Lock() |
|||
{ |
|||
return new PixelAccessorRgba32(this); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,148 @@ |
|||
namespace GenericImage |
|||
{ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
using GenericImage.PackedVectors; |
|||
|
|||
/// <summary>
|
|||
/// Provides per-pixel access to an images pixels.
|
|||
/// </summary>
|
|||
public sealed unsafe class PixelAccessorRgba32 : IPixelAccessor |
|||
{ |
|||
/// <summary>
|
|||
/// The position of the first pixel in the bitmap.
|
|||
/// </summary>
|
|||
private Rgba32* pixelsBase; |
|||
|
|||
/// <summary>
|
|||
/// Provides a way to access the pixels from unmanaged memory.
|
|||
/// </summary>
|
|||
private GCHandle pixelsHandle; |
|||
|
|||
/// <summary>
|
|||
/// A value indicating whether this instance of the given entity has been disposed.
|
|||
/// </summary>
|
|||
/// <value><see langword="true"/> if this instance has been disposed; otherwise, <see langword="false"/>.</value>
|
|||
/// <remarks>
|
|||
/// If the entity is disposed, it must not be disposed a second
|
|||
/// time. The isDisposed field is set the first time the entity
|
|||
/// is disposed. If the isDisposed field is true, then the Dispose()
|
|||
/// method will not dispose again. This help not to prolong the entity's
|
|||
/// life in the Garbage Collector.
|
|||
/// </remarks>
|
|||
private bool isDisposed; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PixelAccessorRgba32"/> class.
|
|||
/// </summary>
|
|||
/// <param name="image">
|
|||
/// The image to provide pixel access for.
|
|||
/// </param>
|
|||
public PixelAccessorRgba32(IImageBase<Rgba32> image) |
|||
{ |
|||
//Guard.NotNull(image, nameof(image));
|
|||
//Guard.MustBeGreaterThan(image.Width, 0, "image width");
|
|||
//Guard.MustBeGreaterThan(image.Height, 0, "image height");
|
|||
|
|||
this.Width = image.Width; |
|||
this.Height = image.Height; |
|||
|
|||
this.pixelsHandle = GCHandle.Alloc(image.Pixels, GCHandleType.Pinned); |
|||
this.pixelsBase = (Rgba32*)this.pixelsHandle.AddrOfPinnedObject().ToPointer(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Finalizes an instance of the <see cref="PixelAccessorRgba32"/> class.
|
|||
/// </summary>
|
|||
~PixelAccessorRgba32() |
|||
{ |
|||
this.Dispose(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the width of the image.
|
|||
/// </summary>
|
|||
public int Width { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the height of the image.
|
|||
/// </summary>
|
|||
public int Height { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the color of a pixel at the specified position.
|
|||
/// </summary>
|
|||
/// <param name="x">
|
|||
/// The x-coordinate of the pixel. Must be greater
|
|||
/// than zero and smaller than the width of the pixel.
|
|||
/// </param>
|
|||
/// <param name="y">
|
|||
/// The y-coordinate of the pixel. Must be greater
|
|||
/// than zero and smaller than the width of the pixel.
|
|||
/// </param>
|
|||
/// <returns>The <see cref="IPackedVector"/> at the specified position.</returns>
|
|||
public IPackedVector this[int x, int y] |
|||
{ |
|||
get |
|||
{ |
|||
#if DEBUG
|
|||
if ((x < 0) || (x >= this.Width)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(x), "Value cannot be less than zero or greater than the bitmap width."); |
|||
} |
|||
|
|||
if ((y < 0) || (y >= this.Height)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(y), "Value cannot be less than zero or greater than the bitmap height."); |
|||
} |
|||
#endif
|
|||
return *(this.pixelsBase + ((y * this.Width) + x)); |
|||
} |
|||
|
|||
set |
|||
{ |
|||
#if DEBUG
|
|||
if ((x < 0) || (x >= this.Width)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(x), "Value cannot be less than zero or greater than the bitmap width."); |
|||
} |
|||
|
|||
if ((y < 0) || (y >= this.Height)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(y), "Value cannot be less than zero or greater than the bitmap height."); |
|||
} |
|||
#endif
|
|||
*(this.pixelsBase + ((y * this.Width) + x)) = (Rgba32)value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
|||
/// </summary>
|
|||
public void Dispose() |
|||
{ |
|||
if (this.isDisposed) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (this.pixelsHandle.IsAllocated) |
|||
{ |
|||
this.pixelsHandle.Free(); |
|||
} |
|||
|
|||
this.pixelsBase = null; |
|||
|
|||
// Note disposing is done.
|
|||
this.isDisposed = true; |
|||
|
|||
// This object will be cleaned up by the Dispose method.
|
|||
// Therefore, you should call GC.SuppressFinalize to
|
|||
// take this object off the finalization queue
|
|||
// and prevent finalization code for this object
|
|||
// from executing a second time.
|
|||
GC.SuppressFinalize(this); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue