From e23d8dfe2cebeb4ed374b47c6a72fb91d1aab412 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Sun, 11 Dec 2016 15:01:24 +0100 Subject: [PATCH] Changed PixelRow into a PixelArea. --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 6 +- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 4 +- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 4 +- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 2 +- src/ImageSharp/Image/PixelAccessor.cs | 243 +++++++++++------- .../Image/{PixelRow.cs => PixelArea.cs} | 89 +++++-- src/ImageSharp/PixelAccessor.cs | 122 +++++---- .../Image/PixelAccessorTests.cs | 8 +- 8 files changed, 304 insertions(+), 174 deletions(-) rename src/ImageSharp/Image/{PixelRow.cs => PixelArea.cs} (65%) diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 7c3e842aa..49b88f902 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -281,7 +281,7 @@ namespace ImageSharp.Formats const int ComponentCount = 2; TColor color = default(TColor); - using (PixelRow row = new PixelRow(width, ComponentOrder.XYZ)) + using (PixelArea row = new PixelArea(width, ComponentOrder.XYZ)) { for (int y = 0; y < height; y++) { @@ -320,7 +320,7 @@ namespace ImageSharp.Formats where TPacked : struct { int padding = CalculatePadding(width, 3); - using (PixelRow row = new PixelRow(width, ComponentOrder.ZYX, padding)) + using (PixelArea row = new PixelArea(width, ComponentOrder.ZYX, padding)) { for (int y = 0; y < height; y++) { @@ -346,7 +346,7 @@ namespace ImageSharp.Formats where TPacked : struct { int padding = CalculatePadding(width, 4); - using (PixelRow row = new PixelRow(width, ComponentOrder.ZYXW, padding)) + using (PixelArea row = new PixelArea(width, ComponentOrder.ZYXW, padding)) { for (int y = 0; y < height; y++) { diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 7c3d18b93..42f159096 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -155,7 +155,7 @@ namespace ImageSharp.Formats where TColor : struct, IPackedPixel where TPacked : struct { - using (PixelRow row = new PixelRow(pixels.Width, ComponentOrder.ZYXW, this.padding)) + using (PixelArea row = new PixelArea(pixels.Width, ComponentOrder.ZYXW, this.padding)) { for (int y = pixels.Height - 1; y >= 0; y--) { @@ -176,7 +176,7 @@ namespace ImageSharp.Formats where TColor : struct, IPackedPixel where TPacked : struct { - using (PixelRow row = new PixelRow(pixels.Width, ComponentOrder.ZYX, this.padding)) + using (PixelArea row = new PixelArea(pixels.Width, ComponentOrder.ZYX, this.padding)) { for (int y = pixels.Height - 1; y >= 0; y--) { diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 0ae8d26b6..c8a22610d 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -339,7 +339,7 @@ namespace ImageSharp.Formats using (PixelAccessor pixelAccessor = image.Lock()) { - using (PixelRow pixelRow = new PixelRow(imageWidth, ComponentOrder.XYZW)) + using (PixelArea pixelRow = new PixelArea(imageWidth, ComponentOrder.XYZW)) { for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++) { @@ -445,7 +445,7 @@ namespace ImageSharp.Formats } else { - using (PixelRow emptyRow = new PixelRow(this.restoreArea.Value.Width, ComponentOrder.XYZW)) + using (PixelArea emptyRow = new PixelArea(this.restoreArea.Value.Width, ComponentOrder.XYZW)) { using (PixelAccessor pixelAccessor = frame.Lock()) { diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 434089e08..a23c19b51 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -322,7 +322,7 @@ namespace ImageSharp.Formats where TPacked : struct { // We can use the optimized PixelAccessor here and copy the bytes in unmanaged memory. - using (PixelRow pixelRow = new PixelRow(this.width, rawScanline, this.bytesPerPixel == 4 ? ComponentOrder.XYZW : ComponentOrder.XYZ)) + using (PixelArea pixelRow = new PixelArea(this.width, rawScanline, this.bytesPerPixel == 4 ? ComponentOrder.XYZW : ComponentOrder.XYZ)) { pixels.CopyTo(pixelRow, row); } diff --git a/src/ImageSharp/Image/PixelAccessor.cs b/src/ImageSharp/Image/PixelAccessor.cs index 8f693584b..87cef890c 100644 --- a/src/ImageSharp/Image/PixelAccessor.cs +++ b/src/ImageSharp/Image/PixelAccessor.cs @@ -177,27 +177,32 @@ namespace ImageSharp /// /// Copied a row of pixels from the image. /// - /// The row. + /// The area. /// The target row index. /// The target column index. /// /// Thrown when an unsupported component order value is passed. /// - public void CopyFrom(PixelRow row, int targetY, int targetX = 0) + public void CopyFrom(PixelArea area, int targetY, int targetX = 0) { - switch (row.ComponentOrder) + int width = Math.Min(area.Width, this.Width - targetX); + int height = Math.Min(area.Height, this.Height - targetY); + + CheckDimensions(width, height); + + switch (area.ComponentOrder) { case ComponentOrder.ZYX: - this.CopyFromZYX(row, targetY, targetX, Math.Min(row.Width, this.Width)); + this.CopyFromZYX(area, targetY, targetX, width, height); break; case ComponentOrder.ZYXW: - this.CopyFromZYXW(row, targetY, targetX, Math.Min(row.Width, this.Width)); + this.CopyFromZYXW(area, targetY, targetX, width, height); break; case ComponentOrder.XYZ: - this.CopyFromXYZ(row, targetY, targetX, Math.Min(row.Width, this.Width)); + this.CopyFromXYZ(area, targetY, targetX, width, height); break; case ComponentOrder.XYZW: - this.CopyFromXYZW(row, targetY, targetX, Math.Min(row.Width, this.Width)); + this.CopyFromXYZW(area, targetY, targetX, width, height); break; default: throw new NotSupportedException(); @@ -205,28 +210,34 @@ namespace ImageSharp } /// - /// Copied a row of pixels to the image. + /// Copied an area of pixels to the image. /// - /// The row. + /// The area. /// The source row index. + /// The source column index. /// /// Thrown when an unsupported component order value is passed. /// - public void CopyTo(PixelRow row, int sourceY) + public void CopyTo(PixelArea area, int sourceY, int sourceX = 0) { - switch (row.ComponentOrder) + int width = Math.Min(area.Width, this.Width - sourceX); + int height = Math.Min(area.Height, this.Height - sourceY); + + CheckDimensions(width, height); + + switch (area.ComponentOrder) { case ComponentOrder.ZYX: - this.CopyToZYX(row, sourceY, Math.Min(row.Width, this.Width)); + this.CopyToZYX(area, sourceY, sourceX, width, height); break; case ComponentOrder.ZYXW: - this.CopyToZYXW(row, sourceY, Math.Min(row.Width, this.Width)); + this.CopyToZYXW(area, sourceY, sourceX, width, height); break; case ComponentOrder.XYZ: - this.CopyToXYZ(row, sourceY, Math.Min(row.Width, this.Width)); + this.CopyToXYZ(area, sourceY, sourceX, width, height); break; case ComponentOrder.XYZW: - this.CopyToXYZW(row, sourceY, Math.Min(row.Width, this.Width)); + this.CopyToXYZW(area, sourceY, sourceX, width, height); break; default: throw new NotSupportedException(); @@ -271,166 +282,202 @@ namespace ImageSharp } /// - /// Copies from a row in format. + /// Copies from an area in format. /// - /// The row. + /// The area. /// The target row index. /// The target column index. /// The width. - protected virtual void CopyFromZYX(PixelRow row, int targetY, int targetX, int width) + /// The height. + protected virtual void CopyFromZYX(PixelArea area, int targetY, int targetX, int width, int height) { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY) + targetX; - TColor packed = default(TColor); int size = Unsafe.SizeOf(); - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - packed.PackFromBytes(*(source + 2), *(source + 1), *source, 255); - Unsafe.Write(destination, packed); + byte* source = area.PixelBase + (y * area.RowByteCount); + byte* destination = this.GetRowPointer(targetY + y) + targetX; + + for (int x = 0; x < width; x++) + { + packed.PackFromBytes(*(source + 2), *(source + 1), *source, 255); + Unsafe.Write(destination, packed); - source += 3; - destination += size; + source += 3; + destination += size; + } } } /// - /// Copies from a row in format. + /// Copies from an area in format. /// - /// The row. + /// The area. /// The target row index. /// The target column index. /// The width. - protected virtual void CopyFromZYXW(PixelRow row, int targetY, int targetX, int width) + /// The height. + protected virtual void CopyFromZYXW(PixelArea area, int targetY, int targetX, int width, int height) { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY) + targetX; - TColor packed = default(TColor); int size = Unsafe.SizeOf(); - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - packed.PackFromBytes(*(source + 2), *(source + 1), *source, *(source + 3)); - Unsafe.Write(destination, packed); + byte* source = area.PixelBase + (y * area.RowByteCount); + byte* destination = this.GetRowPointer(targetY + y) + targetX; - source += 4; - destination += size; + for (int x = 0; x < width; x++) + { + packed.PackFromBytes(*(source + 2), *(source + 1), *source, *(source + 3)); + Unsafe.Write(destination, packed); + + source += 4; + destination += size; + } } } /// - /// Copies from a row in format. + /// Copies from an area in format. /// - /// The row. + /// The area. /// The target row index. /// The target column index. /// The width. - protected virtual void CopyFromXYZ(PixelRow row, int targetY, int targetX, int width) + /// The height. + protected virtual void CopyFromXYZ(PixelArea area, int targetY, int targetX, int width, int height) { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY) + targetX; - TColor packed = default(TColor); int size = Unsafe.SizeOf(); - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - packed.PackFromBytes(*source, *(source + 1), *(source + 2), 255); - Unsafe.Write(destination, packed); + byte* source = area.PixelBase + (y * area.RowByteCount); + byte* destination = this.GetRowPointer(targetY + y) + targetX; + + for (int x = 0; x < width; x++) + { + packed.PackFromBytes(*source, *(source + 1), *(source + 2), 255); + Unsafe.Write(destination, packed); - source += 3; - destination += size; + source += 3; + destination += size; + } } } /// - /// Copies from a row in format. + /// Copies from an area in format. /// - /// The row. + /// The area. /// The target row index. /// The target column index. /// The width. - protected virtual void CopyFromXYZW(PixelRow row, int targetY, int targetX, int width) + /// The height. + protected virtual void CopyFromXYZW(PixelArea area, int targetY, int targetX, int width, int height) { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY) + targetX; - TColor packed = default(TColor); int size = Unsafe.SizeOf(); - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - packed.PackFromBytes(*source, *(source + 1), *(source + 2), *(source + 3)); - Unsafe.Write(destination, packed); + byte* source = area.PixelBase + (y * area.RowByteCount); + byte* destination = this.GetRowPointer(targetY + y) + targetX; + + for (int x = 0; x < width; x++) + { + packed.PackFromBytes(*source, *(source + 1), *(source + 2), *(source + 3)); + Unsafe.Write(destination, packed); - source += 4; - destination += size; + source += 4; + destination += size; + } } } /// - /// Copies to a row in format. + /// Copies to an area in format. /// - /// The row. - /// The target row index. + /// The row. + /// The source row index. + /// The source column index. /// The width. - protected virtual void CopyToZYX(PixelRow row, int sourceY, int width) + /// The height. + protected virtual void CopyToZYX(PixelArea area, int sourceY, int sourceX, int width, int height) { - int offset = 0; - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - this[x, sourceY].ToBytes(row.Bytes, offset, ComponentOrder.ZYX); - offset += 3; + int offset = y * area.RowByteCount; + for (int x = 0; x < width; x++) + { + this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.ZYX); + offset += 3; + } } } /// - /// Copies to a row in format. + /// Copies to an area in format. /// - /// The row. - /// The target row index. + /// The row. + /// The source row index. + /// The source column index. /// The width. - protected virtual void CopyToZYXW(PixelRow row, int sourceY, int width) + /// The height. + protected virtual void CopyToZYXW(PixelArea area, int sourceY, int sourceX, int width, int height) { - int offset = 0; - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - this[x, sourceY].ToBytes(row.Bytes, offset, ComponentOrder.ZYXW); - offset += 4; + int offset = y * area.RowByteCount; + for (int x = 0; x < width; x++) + { + this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.ZYXW); + offset += 4; + } } } /// - /// Copies to a row in format. + /// Copies to an area in format. /// - /// The row. - /// The target row index. + /// The row. + /// The source row index. + /// The source column index. /// The width. - protected virtual void CopyToXYZ(PixelRow row, int sourceY, int width) + /// The height. + protected virtual void CopyToXYZ(PixelArea area, int sourceY, int sourceX, int width, int height) { - int offset = 0; - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - this[x, sourceY].ToBytes(row.Bytes, offset, ComponentOrder.XYZ); - offset += 3; + int offset = y * area.RowByteCount; + for (int x = 0; x < width; x++) + { + this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.XYZ); + offset += 3; + } } } /// - /// Copies to a row in format. + /// Copies to an area in format. /// - /// The row. - /// The target row index. + /// The row. + /// The source row index. + /// The source column index. /// The width. - protected virtual void CopyToXYZW(PixelRow row, int sourceY, int width) + /// The height. + protected virtual void CopyToXYZW(PixelArea area, int sourceY, int sourceX, int width, int height) { - int offset = 0; - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - this[x, sourceY].ToBytes(row.Bytes, offset, ComponentOrder.XYZW); - offset += 4; + int offset = y * area.RowByteCount; + for (int x = 0; x < width; x++) + { + this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.XYZW); + offset += 4; + } } } @@ -446,6 +493,20 @@ namespace ImageSharp return this.pixelsBase + ((targetY * this.Width) * Unsafe.SizeOf()); } + [Conditional("DEBUG")] + private void CheckDimensions(int width, int height) + { + if (width < 1) + { + throw new ArgumentOutOfRangeException(nameof(width), width, $"Invalid area size specified."); + } + + if (height < 1) + { + throw new ArgumentOutOfRangeException(nameof(height), height, $"Invalid area size specified."); + } + } + /// /// Checks the coordinates to ensure they are within bounds. /// diff --git a/src/ImageSharp/Image/PixelRow.cs b/src/ImageSharp/Image/PixelArea.cs similarity index 65% rename from src/ImageSharp/Image/PixelRow.cs rename to src/ImageSharp/Image/PixelArea.cs index a97e49deb..f2b828860 100644 --- a/src/ImageSharp/Image/PixelRow.cs +++ b/src/ImageSharp/Image/PixelArea.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // @@ -6,16 +6,17 @@ namespace ImageSharp { using System; + using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; /// - /// Represents a row of generic pixels. + /// Represents an area of generic pixels. /// /// The pixel format. /// The packed format. uint, long, float. - public sealed unsafe class PixelRow : IDisposable + public sealed unsafe class PixelArea : IDisposable where TColor : struct, IPackedPixel where TPacked : struct { @@ -41,7 +42,7 @@ namespace ImageSharp private bool isDisposed; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The width. /// The bytes. @@ -49,15 +50,29 @@ namespace ImageSharp /// /// Thrown if is the incorrect length. /// - public PixelRow(int width, byte[] bytes, ComponentOrder componentOrder) + public PixelArea(int width, byte[] bytes, ComponentOrder componentOrder) + : this(width, 1, bytes, componentOrder) { - if (bytes.Length != width * GetComponentCount(componentOrder)) - { - throw new ArgumentOutOfRangeException($"Invalid byte array length. Length {bytes.Length}; Should be {width * GetComponentCount(componentOrder)}."); - } + } + + /// + /// Initializes a new instance of the class. + /// + /// The width. + /// The height. + /// The bytes. + /// The component order. + /// + /// Thrown if is the incorrect length. + /// + public PixelArea(int width, int height, byte[] bytes, ComponentOrder componentOrder) + { + this.CheckBytesLength(width, height, bytes, componentOrder); this.Width = width; + this.Height = height; this.ComponentOrder = componentOrder; + this.RowByteCount = width * GetComponentCount(componentOrder); this.Bytes = bytes; this.pixelsHandle = GCHandle.Alloc(this.Bytes, GCHandleType.Pinned); @@ -67,26 +82,40 @@ namespace ImageSharp } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The width. + /// The width. /// The component order. - public PixelRow(int width, ComponentOrder componentOrder) - : this(width, componentOrder, 0) + public PixelArea(int width, ComponentOrder componentOrder) + : this(width, 1, componentOrder, 0) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The width. /// The component order. /// The number of bytes to pad each row. - public PixelRow(int width, ComponentOrder componentOrder, int padding) + public PixelArea(int width, ComponentOrder componentOrder, int padding) + : this(width, 1, componentOrder, padding) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The width. + /// The height. + /// The component order. + /// The number of bytes to pad each row. + public PixelArea(int width, int height, ComponentOrder componentOrder, int padding) { this.Width = width; + this.Height = height; this.ComponentOrder = componentOrder; - this.Bytes = new byte[(width * GetComponentCount(componentOrder)) + padding]; + this.RowByteCount = (width * GetComponentCount(componentOrder)) + padding; + this.Bytes = new byte[this.RowByteCount * height]; this.pixelsHandle = GCHandle.Alloc(this.Bytes, GCHandleType.Pinned); // TODO: Why is Resharper warning us about an impure method call? @@ -95,9 +124,9 @@ namespace ImageSharp } /// - /// Finalizes an instance of the class. + /// Finalizes an instance of the class. /// - ~PixelRow() + ~PixelArea() { this.Dispose(); } @@ -128,7 +157,17 @@ namespace ImageSharp public int Width { get; } /// - /// Reads the stream to the row. + /// Gets the height. + /// + public int Height { get; } + + /// + /// Gets number of bytes in a row. + /// + public int RowByteCount { get; } + + /// + /// Reads the stream to the area. /// /// The stream. public void Read(Stream stream) @@ -137,7 +176,7 @@ namespace ImageSharp } /// - /// Writes the row to the stream. + /// Writes the area to the stream. /// /// The stream. public void Write(Stream stream) @@ -210,5 +249,15 @@ namespace ImageSharp throw new NotSupportedException(); } + + [Conditional("DEBUG")] + private void CheckBytesLength(int width, int height, byte[] bytes, ComponentOrder componentOrder) + { + int requiredLength = (width * GetComponentCount(componentOrder)) * height; + if (bytes.Length != requiredLength) + { + throw new ArgumentOutOfRangeException(nameof(bytes), $"Invalid byte array length. Length {bytes.Length}; Should be {requiredLength}."); + } + } } } diff --git a/src/ImageSharp/PixelAccessor.cs b/src/ImageSharp/PixelAccessor.cs index ff0abddf9..e4d1a9ea7 100644 --- a/src/ImageSharp/PixelAccessor.cs +++ b/src/ImageSharp/PixelAccessor.cs @@ -22,91 +22,111 @@ namespace ImageSharp } /// - protected override void CopyFromXYZW(PixelRow row, int targetY, int targetX, int width) + protected override void CopyFromXYZW(PixelArea area, int targetY, int targetX, int width, int height) { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY) + targetX; + uint byteCount = (uint)width * 4; - Unsafe.CopyBlock(destination, source, (uint)width * 4); + for (int y = 0; y < height; y++) + { + byte* source = area.PixelBase + (y * area.RowByteCount); + byte* destination = this.GetRowPointer(targetY + y) + targetX; + + Unsafe.CopyBlock(destination, source, byteCount); + } } /// - protected override void CopyFromXYZ(PixelRow row, int targetY, int targetX, int width) + protected override void CopyFromXYZ(PixelArea area, int targetY, int targetX, int width, int height) { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY) + targetX; - - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - Unsafe.Write(destination, (uint)(*source << 0 | *(source + 1) << 8 | *(source + 2) << 16 | 255 << 24)); + byte* source = area.PixelBase + (y * area.RowByteCount); + byte* destination = this.GetRowPointer(targetY + y) + targetX; - source += 3; - destination += 4; + 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(PixelRow row, int targetY, int targetX, int width) + protected override void CopyFromZYX(PixelArea area, int targetY, int targetX, int width, int height) { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY) + targetX; - - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | 255 << 24)); + byte* source = area.PixelBase + (y * area.RowByteCount); + byte* destination = this.GetRowPointer(targetY + y) + targetX; + + 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; + source += 3; + destination += 4; + } } } /// - protected override void CopyFromZYXW(PixelRow row, int targetY, int targetX, int width) + protected override void CopyFromZYXW(PixelArea area, int targetY, int targetX, int width, int height) { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY) + targetX; - - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | *(source + 3) << 24)); + byte* source = area.PixelBase + (y * area.RowByteCount); + byte* destination = this.GetRowPointer(targetY + y) + targetX; + + 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; + source += 4; + destination += 4; + } } } /// - protected override void CopyToZYX(PixelRow row, int sourceY, int width) + protected override void CopyToZYX(PixelArea area, int sourceY, int sourceX, int width, int height) { - byte* source = this.GetRowPointer(sourceY); - byte* destination = row.PixelBase; - - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - *destination = *(source + 2); - *(destination + 1) = *(source + 1); - *(destination + 2) = *(source + 0); - - source += 4; - destination += 3; + byte* source = this.GetRowPointer(sourceY + y) + sourceX; + byte* destination = area.PixelBase + (y * area.RowByteCount); + + 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 CopyToZYXW(PixelRow row, int sourceY, int width) + protected override void CopyToZYXW(PixelArea area, int sourceY, int sourceX, int width, int height) { - byte* source = this.GetRowPointer(sourceY); - byte* destination = row.PixelBase; - - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - *destination = *(source + 2); - *(destination + 1) = *(source + 1); - *(destination + 2) = *(source + 0); - *(destination + 3) = *(source + 3); - - source += 4; - destination += 4; + byte* source = this.GetRowPointer(sourceY + y) + sourceX; + byte* destination = area.PixelBase + (y * area.RowByteCount); + + 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; + } } } } diff --git a/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs b/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs index ab71d8de7..cab4527e7 100644 --- a/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs +++ b/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs @@ -71,7 +71,7 @@ namespace ImageSharp.Tests byte blue = 3; byte alpha = 255; - using (PixelRow row = new PixelRow(1, ComponentOrder.ZYX)) + using (PixelArea row = new PixelArea(1, ComponentOrder.ZYX)) { row.Bytes[0] = blue; row.Bytes[1] = green; @@ -99,7 +99,7 @@ namespace ImageSharp.Tests byte blue = 3; byte alpha = 4; - using (PixelRow row = new PixelRow(1, ComponentOrder.ZYXW)) + using (PixelArea row = new PixelArea(1, ComponentOrder.ZYXW)) { row.Bytes[0] = blue; row.Bytes[1] = green; @@ -127,7 +127,7 @@ namespace ImageSharp.Tests byte green = 2; byte blue = 3; - using (PixelRow row = new PixelRow(1, ComponentOrder.ZYX)) + using (PixelArea row = new PixelArea(1, ComponentOrder.ZYX)) { pixels[0, 0] = (TColor) (object) new Color(red, green, blue); @@ -151,7 +151,7 @@ namespace ImageSharp.Tests byte blue = 3; byte alpha = 4; - using (PixelRow row = new PixelRow(1, ComponentOrder.ZYXW)) + using (PixelArea row = new PixelArea(1, ComponentOrder.ZYXW)) { pixels[0, 0] = (TColor) (object) new Color(red, green, blue, alpha);