mirror of https://github.com/SixLabors/ImageSharp
11 changed files with 482 additions and 2 deletions
@ -0,0 +1,12 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
/// <summary>
|
|||
/// The options for decoding tga images. Currently empty, but this may change in the future.
|
|||
/// </summary>
|
|||
internal interface ITgaDecoderOptions |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
/// <summary>
|
|||
/// Registers the image encoders, decoders and mime type detectors for the tga format.
|
|||
/// </summary>
|
|||
public sealed class TgaConfigurationModule : IConfigurationModule |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public void Configure(Configuration configuration) |
|||
{ |
|||
configuration.ImageFormatsManager.SetDecoder(TgaFormat.Instance, new TgaDecoder()); |
|||
configuration.ImageFormatsManager.AddImageFormatDetector(new TgaImageFormatDetector()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
internal static class TgaConstants |
|||
{ |
|||
/// <summary>
|
|||
/// The list of mimetypes that equate to a targa file.
|
|||
/// </summary>
|
|||
public static readonly IEnumerable<string> MimeTypes = new[] { "image/x-tga", "image/x-targa" }; |
|||
|
|||
/// <summary>
|
|||
/// The list of file extensions that equate to a targa file.
|
|||
/// </summary>
|
|||
public static readonly IEnumerable<string> FileExtensions = new[] { "tga", "vda", "icb", "vst" }; |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.IO; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
/// <summary>
|
|||
/// Image decoder for Truevision TGA images.
|
|||
/// </summary>
|
|||
public sealed class TgaDecoder : IImageDecoder, ITgaDecoderOptions, IImageInfoDetector |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
Guard.NotNull(stream, nameof(stream)); |
|||
|
|||
return new TgaDecoderCore(configuration, this).Decode<TPixel>(stream); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Image Decode(Configuration configuration, Stream stream) => this.Decode<Rgba32>(configuration, stream); |
|||
|
|||
/// <inheritdoc/>
|
|||
public IImageInfo Identify(Configuration configuration, Stream stream) |
|||
{ |
|||
Guard.NotNull(stream, nameof(stream)); |
|||
|
|||
return new TgaDecoderCore(configuration, this).Identify(stream); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,125 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.IO; |
|||
|
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.Metadata; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
internal sealed class TgaDecoderCore |
|||
{ |
|||
/// <summary>
|
|||
/// The metadata.
|
|||
/// </summary>
|
|||
private ImageMetadata metadata; |
|||
|
|||
/// <summary>
|
|||
/// The file header containing general information about the image.
|
|||
/// </summary>
|
|||
private TgaFileHeader fileHeader; |
|||
|
|||
/// <summary>
|
|||
/// The global configuration.
|
|||
/// </summary>
|
|||
private readonly Configuration configuration; |
|||
|
|||
/// <summary>
|
|||
/// Used for allocating memory during processing operations.
|
|||
/// </summary>
|
|||
private readonly MemoryAllocator memoryAllocator; |
|||
|
|||
/// <summary>
|
|||
/// The stream to decode from.
|
|||
/// </summary>
|
|||
private Stream currentStream; |
|||
|
|||
/// <summary>
|
|||
/// The bitmap decoder options.
|
|||
/// </summary>
|
|||
private readonly ITgaDecoderOptions options; |
|||
|
|||
public TgaDecoderCore(Configuration configuration, ITgaDecoderOptions options) |
|||
{ |
|||
this.configuration = configuration; |
|||
this.memoryAllocator = configuration.MemoryAllocator; |
|||
this.options = options; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Decodes the image from the specified stream.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="stream">The stream, where the image should be decoded from. Cannot be null.</param>
|
|||
/// <exception cref="System.ArgumentNullException">
|
|||
/// <para><paramref name="stream"/> is null.</para>
|
|||
/// </exception>
|
|||
/// <returns>The decoded image.</returns>
|
|||
public Image<TPixel> Decode<TPixel>(Stream stream) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
try |
|||
{ |
|||
this.ReadFileHeader(stream); |
|||
|
|||
var image = new Image<TPixel>(this.configuration, this.fileHeader.Width, this.fileHeader.Height, this.metadata); |
|||
Buffer2D<TPixel> pixels = image.GetRootFramePixelBuffer(); |
|||
|
|||
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<TPixel> pixelSpan = pixels.GetRowSpan(y); |
|||
PixelOperations<TPixel>.Instance.FromBgr24Bytes( |
|||
this.configuration, |
|||
row.GetSpan(), |
|||
pixelSpan, |
|||
this.fileHeader.Width); |
|||
} |
|||
} |
|||
|
|||
return image; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
throw new ImageFormatException("TGA image does not have a valid format.", e); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Reads the raw image information from the specified stream.
|
|||
/// </summary>
|
|||
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
|
|||
public IImageInfo Identify(Stream stream) |
|||
{ |
|||
this.ReadFileHeader(stream); |
|||
return new ImageInfo( |
|||
new PixelTypeInfo(this.fileHeader.PixelDepth), |
|||
this.fileHeader.Width, |
|||
this.fileHeader.Height, |
|||
this.metadata); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Reads the tga file header from the stream.
|
|||
/// </summary>
|
|||
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
|
|||
private void ReadFileHeader(Stream stream) |
|||
{ |
|||
this.currentStream = stream; |
|||
|
|||
#if NETCOREAPP2_1
|
|||
Span<byte> buffer = stackalloc byte[TgaFileHeader.Size]; |
|||
#else
|
|||
var buffer = new byte[TgaFileHeader.Size]; |
|||
#endif
|
|||
this.currentStream.Read(buffer, 0, TgaFileHeader.Size); |
|||
this.fileHeader = TgaFileHeader.Parse(buffer); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,139 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
/// <summary>
|
|||
/// This block of bytes tells the application detailed information about the targa image.
|
|||
/// <see href="https://www.fileformat.info/format/tga/egff.htm"/>
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential, Pack = 1)] |
|||
internal readonly struct TgaFileHeader |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the size of the data structure in the targa file.
|
|||
/// </summary>
|
|||
public const int Size = 18; |
|||
|
|||
public TgaFileHeader( |
|||
byte idLength, |
|||
byte colorMapType, |
|||
TgaImageType imageType, |
|||
short cMapStart, |
|||
short cMapLength, |
|||
byte cMapDepth, |
|||
short xOffset, |
|||
short yOffset, |
|||
short width, |
|||
short height, |
|||
byte pixelDepth, |
|||
byte imageDescriptor) |
|||
{ |
|||
this.IdLength = idLength; |
|||
this.ColorMapType = colorMapType; |
|||
this.ImageType = imageType; |
|||
this.CMapStart = cMapStart; |
|||
this.CMapLength = cMapLength; |
|||
this.CMapDepth = cMapDepth; |
|||
this.XOffset = xOffset; |
|||
this.YOffset = yOffset; |
|||
this.Width = width; |
|||
this.Height = height; |
|||
this.PixelDepth = pixelDepth; |
|||
this.ImageDescriptor = imageDescriptor; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the id length.
|
|||
/// This field identifies the number of bytes contained in Field 6, the Image ID Field. The maximum number
|
|||
/// of characters is 255. A value of zero indicates that no Image ID field is included with the image.
|
|||
/// </summary>
|
|||
public byte IdLength { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the color map type.
|
|||
/// This field indicates the type of color map (if any) included with the image. There are currently 2 defined
|
|||
/// values for this field:
|
|||
/// 0 - indicates that no color-map data is included with this image.
|
|||
/// 1 - indicates that a color-map is included with this image.
|
|||
/// </summary>
|
|||
public byte ColorMapType { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the image type.
|
|||
/// The TGA File Format can be used to store Pseudo-Color, True-Color and Direct-Color images of various
|
|||
/// pixel depths.
|
|||
/// </summary>
|
|||
public TgaImageType ImageType { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the start of the color map.
|
|||
/// This field and its sub-fields describe the color map (if any) used for the image. If the Color Map Type field
|
|||
/// is set to zero, indicating that no color map exists, then these 5 bytes should be set to zero.
|
|||
/// </summary>
|
|||
public short CMapStart { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the total number of color map entries included.
|
|||
/// </summary>
|
|||
public short CMapLength { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of bits per entry. Typically 15, 16, 24 or 32-bit values are used.
|
|||
/// </summary>
|
|||
public byte CMapDepth { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the XOffset.
|
|||
/// These bytes specify the absolute horizontal coordinate for the lower left
|
|||
/// corner of the image as it is positioned on a display device having an
|
|||
/// origin at the lower left of the screen.
|
|||
/// </summary>
|
|||
public short XOffset { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the YOffset.
|
|||
/// These bytes specify the absolute vertical coordinate for the lower left
|
|||
/// corner of the image as it is positioned on a display device having an
|
|||
/// origin at the lower left of the screen.
|
|||
/// </summary>
|
|||
public short YOffset { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the width of the image in pixels.
|
|||
/// </summary>
|
|||
public short Width { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the height of the image in pixels.
|
|||
/// </summary>
|
|||
public short Height { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of bits per pixel. This number includes
|
|||
/// the Attribute or Alpha channel bits. Common values are 8, 16, 24 and
|
|||
/// 32 but other pixel depths could be used.
|
|||
/// </summary>
|
|||
public byte PixelDepth { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the ImageDescriptor.
|
|||
/// ImageDescriptor contains two pieces of information.
|
|||
/// Bits 0 through 3 contain the number of attribute bits per pixel.
|
|||
/// Attribute bits are found only in pixels for the 16- and 32-bit flavors of the TGA format and are called alpha channel,
|
|||
/// overlay, or interrupt bits. Bits 4 and 5 contain the image origin location (coordinate 0,0) of the image.
|
|||
/// This position may be any of the four corners of the display screen.
|
|||
/// When both of these bits are set to zero, the image origin is the lower-left corner of the screen.
|
|||
/// Bits 6 and 7 of the ImageDescriptor field are unused and should be set to 0.
|
|||
/// </summary>
|
|||
public byte ImageDescriptor { get; } |
|||
|
|||
public static TgaFileHeader Parse(Span<byte> data) |
|||
{ |
|||
return MemoryMarshal.Cast<byte, TgaFileHeader>(data)[0]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
/// <summary>
|
|||
/// Registers the image encoders, decoders and mime type detectors for the tga format.
|
|||
/// </summary>
|
|||
public sealed class TgaFormat : IImageFormat<TgaMetadata> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the current instance.
|
|||
/// </summary>
|
|||
public static TgaFormat Instance { get; } = new TgaFormat(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public string Name => "TGA"; |
|||
|
|||
/// <inheritdoc/>
|
|||
public string DefaultMimeType => "image/tga"; |
|||
|
|||
/// <inheritdoc/>
|
|||
public IEnumerable<string> MimeTypes => TgaConstants.MimeTypes; |
|||
|
|||
/// <inheritdoc/>
|
|||
public IEnumerable<string> FileExtensions => TgaConstants.FileExtensions; |
|||
|
|||
/// <inheritdoc/>
|
|||
public TgaMetadata CreateDefaultFormatMetadata() => new TgaMetadata(); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
/// <summary>
|
|||
/// Detects tga file headers.
|
|||
/// </summary>
|
|||
public sealed class TgaImageFormatDetector : IImageFormatDetector |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public int HeaderSize => 18; |
|||
|
|||
/// <inheritdoc/>
|
|||
public IImageFormat DetectFormat(ReadOnlySpan<byte> header) |
|||
{ |
|||
return this.IsSupportedFileFormat(header) ? TgaFormat.Instance : null; |
|||
} |
|||
|
|||
private bool IsSupportedFileFormat(ReadOnlySpan<byte> header) |
|||
{ |
|||
return header.Length >= this.HeaderSize; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the tga image type. The TGA File Format can be used to store Pseudo-Color,
|
|||
/// True-Color and Direct-Color images of various pixel depths.
|
|||
/// </summary>
|
|||
public enum TgaImageType : byte |
|||
{ |
|||
/// <summary>
|
|||
/// No image data included.
|
|||
/// Not sure what this is used for.
|
|||
/// </summary>
|
|||
NoImageData = 0, |
|||
|
|||
/// <summary>
|
|||
/// Uncompressed, color mapped image.
|
|||
/// </summary>
|
|||
ColorMapped = 1, |
|||
|
|||
/// <summary>
|
|||
/// Uncompressed true color image.
|
|||
/// </summary>
|
|||
TrueColor = 2, |
|||
|
|||
/// <summary>
|
|||
/// Uncompressed Black and white (grayscale) image.
|
|||
/// </summary>
|
|||
BlackAndWhite = 3, |
|||
|
|||
/// <summary>
|
|||
/// Run length encoded, color mapped image.
|
|||
/// </summary>
|
|||
RleColorMapped = 9, |
|||
|
|||
/// <summary>
|
|||
/// Run length encoded, true color image.
|
|||
/// </summary>
|
|||
RleTrueColor = 10, |
|||
|
|||
/// <summary>
|
|||
/// Run length encoded, black and white (grayscale) image.
|
|||
/// </summary>
|
|||
RleBlackAndWhite = 11, |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tga |
|||
{ |
|||
/// <summary>
|
|||
/// Provides TGA specific metadata information for the image.
|
|||
/// </summary>
|
|||
public class TgaMetadata : IDeepCloneable |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="TgaMetadata"/> class.
|
|||
/// </summary>
|
|||
public TgaMetadata() |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public IDeepCloneable DeepClone() => throw new System.NotImplementedException(); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue