Browse Source

Use DangerousGetRowSpan when run length encode image

pull/2197/head
Brian Popow 4 years ago
parent
commit
95ae124adb
  1. 94
      src/ImageSharp/Formats/Tga/TgaEncoderCore.cs

94
src/ImageSharp/Formats/Tga/TgaEncoderCore.cs

@ -117,7 +117,6 @@ namespace SixLabors.ImageSharp.Formats.Tga
fileHeader.WriteTo(buffer);
stream.Write(buffer, 0, TgaFileHeader.Size);
if (this.compression is TgaCompression.RunLength)
{
this.WriteRunLengthEncodedImage(stream, image.Frames.RootFrame);
@ -175,50 +174,50 @@ namespace SixLabors.ImageSharp.Formats.Tga
{
Rgba32 color = default;
Buffer2D<TPixel> pixels = image.PixelBuffer;
int totalPixels = image.Width * image.Height;
int encodedPixels = 0;
while (encodedPixels < totalPixels)
for (int y = 0; y < image.Height; y++)
{
int x = encodedPixels % pixels.Width;
int y = encodedPixels / pixels.Width;
TPixel currentPixel = pixels[x, y];
currentPixel.ToRgba32(ref color);
byte equalPixelCount = this.FindEqualPixels(pixels, x, y);
// Write the number of equal pixels, with the high bit set, indicating ist a compressed pixel run.
stream.WriteByte((byte)(equalPixelCount | 128));
switch (this.bitsPerPixel)
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y);
for (int x = 0; x < image.Width;)
{
case TgaBitsPerPixel.Pixel8:
int luminance = GetLuminance(currentPixel);
stream.WriteByte((byte)luminance);
break;
case TgaBitsPerPixel.Pixel16:
var bgra5551 = new Bgra5551(color.ToVector4());
BinaryPrimitives.TryWriteInt16LittleEndian(this.buffer, (short)bgra5551.PackedValue);
stream.WriteByte(this.buffer[0]);
stream.WriteByte(this.buffer[1]);
break;
case TgaBitsPerPixel.Pixel24:
stream.WriteByte(color.B);
stream.WriteByte(color.G);
stream.WriteByte(color.R);
break;
case TgaBitsPerPixel.Pixel32:
stream.WriteByte(color.B);
stream.WriteByte(color.G);
stream.WriteByte(color.R);
stream.WriteByte(color.A);
break;
default:
break;
TPixel currentPixel = pixelRow[x];
currentPixel.ToRgba32(ref color);
byte equalPixelCount = this.FindEqualPixels(pixelRow, x);
// Write the number of equal pixels, with the high bit set, indicating ist a compressed pixel run.
stream.WriteByte((byte)(equalPixelCount | 128));
switch (this.bitsPerPixel)
{
case TgaBitsPerPixel.Pixel8:
int luminance = GetLuminance(currentPixel);
stream.WriteByte((byte)luminance);
break;
case TgaBitsPerPixel.Pixel16:
var bgra5551 = new Bgra5551(color.ToVector4());
BinaryPrimitives.TryWriteInt16LittleEndian(this.buffer, (short)bgra5551.PackedValue);
stream.WriteByte(this.buffer[0]);
stream.WriteByte(this.buffer[1]);
break;
case TgaBitsPerPixel.Pixel24:
stream.WriteByte(color.B);
stream.WriteByte(color.G);
stream.WriteByte(color.R);
break;
case TgaBitsPerPixel.Pixel32:
stream.WriteByte(color.B);
stream.WriteByte(color.G);
stream.WriteByte(color.R);
stream.WriteByte(color.A);
break;
default:
break;
}
x += equalPixelCount + 1;
}
encodedPixels += equalPixelCount + 1;
}
}
@ -226,18 +225,17 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// Finds consecutive pixels which have the same value.
/// </summary>
/// <typeparam name="TPixel">The pixel type.</typeparam>
/// <param name="pixels">The pixels of the image.</param>
/// <param name="pixelRow">A pixel row of the image to encode.</param>
/// <param name="xStart">X coordinate to start searching for the same pixels.</param>
/// <param name="yPos">Y coordinate to searching for the same pixels in only one scan line.</param>
/// <returns>The number of equal pixels.</returns>
private byte FindEqualPixels<TPixel>(Buffer2D<TPixel> pixels, int xStart, int yPos)
private byte FindEqualPixels<TPixel>(Span<TPixel> pixelRow, int xStart)
where TPixel : unmanaged, IPixel<TPixel>
{
byte equalPixelCount = 0;
TPixel startPixel = pixels[xStart, yPos];
for (int x = xStart + 1; x < pixels.Width; x++)
TPixel startPixel = pixelRow[xStart];
for (int x = xStart + 1; x < pixelRow.Length; x++)
{
TPixel nextPixel = pixels[x, yPos];
TPixel nextPixel = pixelRow[x];
if (startPixel.Equals(nextPixel))
{
equalPixelCount++;

Loading…
Cancel
Save