diff --git a/src/ImageSharp/Image/PixelAccessor.cs b/src/ImageSharp/Image/PixelAccessor.cs index d6f677264..6e0e45d5e 100644 --- a/src/ImageSharp/Image/PixelAccessor.cs +++ b/src/ImageSharp/Image/PixelAccessor.cs @@ -136,6 +136,27 @@ namespace ImageSharp this.CopyBlock(0, 0, target, 0, 0, target.Width * target.Height); } + public void CopyFrom(PixelRow row, int targetY) + { + switch (row.ComponentOrder) + { + case ComponentOrder.BGR: + this.CopyFromBGR(row, targetY, Math.Min(row.Width, this.Width)); + break; + case ComponentOrder.BGRA: + this.CopyFromBGRA(row, targetY, Math.Min(row.Width, this.Width)); + break; + case ComponentOrder.RGB: + this.CopyFromRGB(row, targetY, Math.Min(row.Width, this.Width)); + break; + case ComponentOrder.RGBA: + this.CopyFromRGBA(row, targetY, Math.Min(row.Width, this.Width)); + break; + default: + throw new NotSupportedException(); + } + } + /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// @@ -164,5 +185,82 @@ namespace ImageSharp // from executing a second time. GC.SuppressFinalize(this); } + + protected virtual void CopyFromBGR(PixelRow row, int targetY, int width) + { + byte* source = row.DataPointer; + byte* destination = this.GetRowPointer(targetY); + + TColor packed = default(TColor); + int size = Unsafe.SizeOf(); + + for (int x = 0; x < width; x++) + { + packed.PackFromBytes(*(source + 2), *(source + 1), *source, 255); + Unsafe.Write(destination, packed); + + source += 3; + destination += size; + } + } + + protected virtual void CopyFromBGRA(PixelRow row, int targetY, int width) + { + byte* source = row.DataPointer; + byte* destination = this.GetRowPointer(targetY); + + TColor packed = default(TColor); + int size = Unsafe.SizeOf(); + + for (int x = 0; x < width; x++) + { + packed.PackFromBytes(*(source + 2), *(source + 1), *source, *(source + 3)); + Unsafe.Write(destination, packed); + + source += 4; + destination += size; + } + } + + protected virtual void CopyFromRGB(PixelRow row, int targetY, int width) + { + byte* source = row.DataPointer; + byte* destination = this.GetRowPointer(targetY); + + TColor packed = default(TColor); + int size = Unsafe.SizeOf(); + + for (int x = 0; x < width; x++) + { + packed.PackFromBytes(*source, *(source + 1), *(source + 2), 255); + Unsafe.Write(destination, packed); + + source += 3; + destination += size; + } + } + + protected virtual void CopyFromRGBA(PixelRow row, int targetY, int width) + { + byte* source = row.DataPointer; + byte* destination = this.GetRowPointer(targetY); + + TColor packed = default(TColor); + int size = Unsafe.SizeOf(); + + for (int x = 0; x < width; x++) + { + packed.PackFromBytes(*source, *(source + 1), *(source + 2), *(source + 3)); + Unsafe.Write(destination, packed); + + source += 4; + destination += size; + } + } + + protected byte* GetRowPointer(int targetY) + { + return this.pixelsBase + ((targetY * this.Width) * Unsafe.SizeOf()); + } } } \ No newline at end of file