Browse Source

Merge pull request #1210 from SixLabors/bp/detectTga

Additionally checks in DetectFormat for TGA files
pull/1574/head
James Jackson-South 6 years ago
committed by GitHub
parent
commit
8d052e8dad
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs
  2. 44
      tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs

31
src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
public sealed class TgaImageFormatDetector : IImageFormatDetector
{
/// <inheritdoc/>
public int HeaderSize => TgaConstants.FileHeaderLength;
public int HeaderSize => 16;
/// <inheritdoc/>
public IImageFormat DetectFormat(ReadOnlySpan<byte> header)
@ -23,15 +23,38 @@ namespace SixLabors.ImageSharp.Formats.Tga
{
if (header.Length >= this.HeaderSize)
{
// There are no magic bytes in a tga file, so at least the image type
// and the colormap type in the header will be checked for a valid value.
// There are no magic bytes in the first few bytes of a tga file,
// so we try to figure out if its a valid tga by checking for valid tga header bytes.
// The color map type should be either 0 or 1, other values are not valid.
if (header[1] != 0 && header[1] != 1)
{
return false;
}
// The third byte is the image type.
var imageType = (TgaImageType)header[2];
return imageType.IsValid();
if (!imageType.IsValid())
{
return false;
}
// If the color map typ is zero, all bytes of the color map specification should also be zeros.
if (header[1] == 0)
{
if (header[3] != 0 || header[4] != 0 || header[5] != 0 || header[6] != 0 || header[7] != 0)
{
return false;
}
}
// The height or the width of the image should not be zero.
if ((header[12] == 0 && header[13] == 0) || (header[14] == 0 && header[15] == 0))
{
return false;
}
return true;
}
return false;

44
tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs

@ -1,34 +1,54 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the GNU Affero General Public License, Version 3.
using System.Collections.Generic;
using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Tga;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Tga
{
public class TgaFileHeaderTests
{
private static readonly byte[] Data =
[Theory]
[InlineData(new byte[] { 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 })] // invalid tga image type.
[InlineData(new byte[] { 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 })] // invalid colormap type.
[InlineData(new byte[] { 0, 0, 1, 5, 5, 5, 5, 5, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 })] // valid colormap type (0), but colomap spec bytes should all be zero.
[InlineData(new byte[] { 0, 0, 1, 0, 0, 0, 0, 8, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 })] // valid colormap type (0), but colomap spec bytes should all be zero.
[InlineData(new byte[] { 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 })] // valid colormap type (0), but colomap spec bytes should all be zero.
[InlineData(new byte[] { 0, 0, 1, 0, 0, 6, 0, 0, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 })] // valid colormap type (0), but colomap spec bytes should all be zero.
[InlineData(new byte[] { 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 })] // valid colormap type (0), but colomap spec bytes should all be zero.
[InlineData(new byte[] { 0, 0, 0, 12, 106, 80, 32, 32, 13, 10, 135, 10, 0, 0, 0, 20, 102, 116 })] // jp2 image header
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, 32, 8 })] // invalid width
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 32, 8 })] // invalid height
public void ImageLoad_WithNoValidTgaHeaderBytes_Throws_UnknownImageFormatException(byte[] data)
{
0,
0,
15 // invalid tga image type
};
private MemoryStream Stream { get; } = new MemoryStream(Data);
using var stream = new MemoryStream(data);
[Fact]
public void ImageLoad_WithInvalidImageType_Throws_UnknownImageFormatException()
{
Assert.Throws<UnknownImageFormatException>(() =>
{
using (Image.Load(Configuration.Default, this.Stream, out IImageFormat _))
using (Image.Load(Configuration.Default, stream, out IImageFormat _))
{
}
});
}
[Theory]
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 }, 250, 195, TgaBitsPerPixel.Pixel32)]
[InlineData(new byte[] { 26, 1, 9, 0, 0, 0, 1, 16, 0, 0, 0, 0, 128, 0, 128, 0, 8, 0 }, 128, 128, TgaBitsPerPixel.Pixel8)]
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 220, 0, 16, 0 }, 220, 220, TgaBitsPerPixel.Pixel16)]
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 124, 0, 24, 32 }, 124, 124, TgaBitsPerPixel.Pixel24)]
public void Identify_WithValidData_Works(byte[] data, int width, int height, TgaBitsPerPixel bitsPerPixel)
{
using var stream = new MemoryStream(data);
IImageInfo info = Image.Identify(stream);
TgaMetadata tgaData = info.Metadata.GetTgaMetadata();
Assert.Equal(bitsPerPixel, tgaData.BitsPerPixel);
Assert.Equal(width, info.Width);
Assert.Equal(height, info.Height);
}
}
}

Loading…
Cancel
Save