diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs index b8068c082..a73f04bcd 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs @@ -69,28 +69,109 @@ namespace SixLabors.ImageSharp.Formats.Tga var image = new Image(this.configuration, this.fileHeader.Width, this.fileHeader.Height, this.metadata); Buffer2D pixels = image.GetRootFramePixelBuffer(); - using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(this.fileHeader.Width, 3, 0)) + switch (this.fileHeader.PixelDepth) { - for (int y = 0; y < this.fileHeader.Height; y++) - { - this.currentStream.Read(row); - Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.FromBgr24Bytes( - this.configuration, - row.GetSpan(), - pixelSpan, - this.fileHeader.Width); - } + case 8: + this.ReadMonoChrome(pixels); + break; + + case 16: + this.ReadBgra16(pixels); + break; + + case 24: + this.ReadBgr24(pixels); + break; + + case 32: + this.ReadBgra32(pixels); + break; + + default: + TgaThrowHelper.ThrowNotSupportedException("Does not support this kind of tga files."); + break; } return image; } - catch (Exception e) + catch (IndexOutOfRangeException e) { throw new ImageFormatException("TGA image does not have a valid format.", e); } } + private void ReadMonoChrome(Buffer2D pixels) + where TPixel : struct, IPixel + { + using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(this.fileHeader.Width, 1, 0)) + { + for (int y = 0; y < this.fileHeader.Height; y++) + { + this.currentStream.Read(row); + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.FromGray8Bytes( + this.configuration, + row.GetSpan(), + pixelSpan, + this.fileHeader.Width); + } + } + } + + private void ReadBgra16(Buffer2D pixels) + where TPixel : struct, IPixel + { + using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(this.fileHeader.Width, 2, 0)) + { + for (int y = 0; y < this.fileHeader.Height; y++) + { + this.currentStream.Read(row); + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.FromBgra5551Bytes( + this.configuration, + row.GetSpan(), + pixelSpan, + this.fileHeader.Width); + } + } + } + + private void ReadBgr24(Buffer2D pixels) + where TPixel : struct, IPixel + { + using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(this.fileHeader.Width, 3, 0)) + { + for (int y = 0; y < this.fileHeader.Height; y++) + { + this.currentStream.Read(row); + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.FromBgr24Bytes( + this.configuration, + row.GetSpan(), + pixelSpan, + this.fileHeader.Width); + } + } + } + + private void ReadBgra32(Buffer2D pixels) + where TPixel : struct, IPixel + { + using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(this.fileHeader.Width, 4, 0)) + { + for (int y = 0; y < this.fileHeader.Height; y++) + { + this.currentStream.Read(row); + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.FromBgra32Bytes( + this.configuration, + row.GetSpan(), + pixelSpan, + this.fileHeader.Width); + } + } + } + /// /// Reads the raw image information from the specified stream. /// diff --git a/src/ImageSharp/Formats/Tga/TgaThrowHelper.cs b/src/ImageSharp/Formats/Tga/TgaThrowHelper.cs new file mode 100644 index 000000000..9e36b2053 --- /dev/null +++ b/src/ImageSharp/Formats/Tga/TgaThrowHelper.cs @@ -0,0 +1,21 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.Formats.Tga +{ + internal static class TgaThrowHelper + { + /// + /// Cold path optimization for throwing -s + /// + /// The error message for the exception. + [MethodImpl(MethodImplOptions.NoInlining)] + public static void ThrowNotSupportedException(string errorMessage) + { + throw new NotSupportedException(errorMessage); + } + } +}