From e18481b20deca1d763123851f3175425cdaa400a Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Tue, 8 Oct 2019 20:53:49 +0200 Subject: [PATCH] Add decoding of 16 and 8 bit rle images --- src/ImageSharp/Formats/Tga/TgaDecoderCore.cs | 78 ++++++++++++++------ 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs index 224a14131..b6b078f6d 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs @@ -74,11 +74,28 @@ namespace SixLabors.ImageSharp.Formats.Tga switch (this.fileHeader.PixelDepth) { case 8: - this.ReadMonoChrome(pixels); + if (this.fileHeader.ImageType.IsRunLengthEncoded()) + { + this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 1); + } + else + { + this.ReadMonoChrome(pixels); + } + break; case 16: - this.ReadBgra16(pixels); + if (this.fileHeader.ImageType.IsRunLengthEncoded()) + { + long currentPosition = this.currentStream.Position; + this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 2); + } + else + { + this.ReadBgra16(pixels); + } + break; case 24: @@ -156,26 +173,7 @@ namespace SixLabors.ImageSharp.Formats.Tga } // We need to set each alpha component value to fully opaque. - // Reset our stream for a second pass. - this.currentStream.Position = currentPosition; - for (int y = 0; y < this.fileHeader.Height; y++) - { - this.currentStream.Read(row); - PixelOperations.Instance.FromBgra5551Bytes( - this.configuration, - row.GetSpan(), - bgraRowSpan, - this.fileHeader.Width); - Span pixelSpan = pixels.GetRowSpan(this.fileHeader.Height - y - 1); - - for (int x = 0; x < this.fileHeader.Width; x++) - { - Bgra5551 bgra = bgraRowSpan[x]; - bgra.PackedValue = (ushort)(bgra.PackedValue | (1 << 15)); - ref TPixel pixel = ref pixelSpan[x]; - pixel.FromBgra5551(bgra); - } - } + this.MakeOpaque(pixels, currentPosition, row, bgraRowSpan); } } @@ -232,12 +230,19 @@ namespace SixLabors.ImageSharp.Formats.Tga int idx = rowStartIdx + (x * bytesPerPixel); switch (bytesPerPixel) { - case 4: - color.FromBgra32(Unsafe.As(ref bufferSpan[idx])); + case 1: + color.FromGray8(Unsafe.As(ref bufferSpan[idx])); + break; + case 2: + bufferSpan[idx + 1] = (byte)(bufferSpan[idx + 1] | 128); + color.FromBgra5551(Unsafe.As(ref bufferSpan[idx])); break; case 3: color.FromBgr24(Unsafe.As(ref bufferSpan[idx])); break; + case 4: + color.FromBgra32(Unsafe.As(ref bufferSpan[idx])); + break; } pixelRow[x] = color; @@ -283,6 +288,31 @@ namespace SixLabors.ImageSharp.Formats.Tga } } + private void MakeOpaque(Buffer2D pixels, long currentPosition, IManagedByteBuffer row, Span bgraRowSpan) + where TPixel : struct, IPixel + { + // Reset our stream for a second pass. + this.currentStream.Position = currentPosition; + for (int y = 0; y < this.fileHeader.Height; y++) + { + this.currentStream.Read(row); + PixelOperations.Instance.FromBgra5551Bytes( + this.configuration, + row.GetSpan(), + bgraRowSpan, + this.fileHeader.Width); + Span pixelSpan = pixels.GetRowSpan(this.fileHeader.Height - y - 1); + + for (int x = 0; x < this.fileHeader.Width; x++) + { + Bgra5551 bgra = bgraRowSpan[x]; + bgra.PackedValue = (ushort)(bgra.PackedValue | (1 << 15)); + ref TPixel pixel = ref pixelSpan[x]; + pixel.FromBgra5551(bgra); + } + } + } + /// /// Reads the raw image information from the specified stream. ///