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

Loading…
Cancel
Save