Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ ClientBin/
*.[Pp]ublish.xml
*.pfx
*.publishsettings
.devcontainer
.devcontainer/*

# RIA/Silverlight projects
Generated_Code/
Expand Down
21 changes: 21 additions & 0 deletions src/MigrationTools.Tests/MigrationTools.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,27 @@
<ProjectReference Include="..\MigrationTools.Clients.FileSystem\MigrationTools.Clients.FileSystem.csproj" />
<ProjectReference Include="..\MigrationTools.Shadows\MigrationTools.Shadows.csproj" />
<ProjectReference Include="..\MigrationTools\MigrationTools.csproj" />
</ItemGroup>

<ItemGroup>
<Content Include="..\MigrationTools.Tests\Tools\Infrastructure\Assets\bmpsample.bmp">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\MigrationTools.Tests\Tools\Infrastructure\Assets\gifsample.gif">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\MigrationTools.Tests\Tools\Infrastructure\Assets\jpgsample.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\MigrationTools.Tests\Tools\Infrastructure\Assets\tiffsample.tiff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\MigrationTools.Tests\Tools\Infrastructure\Assets\pngsample.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\MigrationTools.Tests\Tools\Infrastructure\Assets\svgsample.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
Expand Down
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MigrationTools.DataContracts;
using MigrationTools.Options;
using MigrationTools.Tools;
using MigrationTools.Tools.Infrastructure;

namespace MigrationTools.Tests.Tools.Infrastructure
{
[TestClass]
public class EmbededImagesRepairToolBaseTests
{
private static byte[] LoadAsset(string name)
{
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tools", "Infrastructure", "Assets", name);
return File.ReadAllBytes(path);
}

[TestMethod]
public void ShouldDetectJpegWithPhotoshopMetadata_FromFile()
{
byte[] bytes = LoadAsset("jpgsample.jpg");
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(bytes);
Assert.AreEqual("jpeg", format);
}

[TestMethod]
public void ShouldDetectPng_FromFile()
{
byte[] bytes = LoadAsset("pngsample.png");
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(bytes);
Assert.AreEqual("png", format);
}

[TestMethod]
public void ShouldDetectTiff_FromFile()
{
byte[] bytes = LoadAsset("tiffsample.tiff");
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(bytes);
Assert.AreEqual("tiff", format);
}

[TestMethod]
public void ShouldDetectGif_FromFile()
{
byte[] bytes = LoadAsset("gifsample.gif");
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(bytes);
Assert.AreEqual("gif", format);
}

[TestMethod]
public void ShouldDetectSvg_FromFile()
{
byte[] bytes = LoadAsset("svgsample.svg");
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(bytes);
Assert.AreEqual("svg", format);
}

[TestMethod]
public void ShouldDetectBmp()
{
byte[] bmpHeader = new byte[] { 66, 77 }; // "BM"
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(bmpHeader);
Assert.AreEqual("bmp", format);
}

[TestMethod]
public void ShouldDetectSVG()
{
byte[] svgHeader = Encoding.ASCII.GetBytes("<svg");
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(svgHeader);
Assert.AreEqual("svg", format);
}

[TestMethod]
public void ShouldDetectGIF87a()
{
byte[] gifHeader = Encoding.ASCII.GetBytes("GIF87a");
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(gifHeader);
Assert.AreEqual("gif", format);
}

[TestMethod]
public void ShouldDetectGIF89a()
{
byte[] gifHeader = Encoding.ASCII.GetBytes("GIF89a");
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(gifHeader);
Assert.AreEqual("gif", format);
}

[TestMethod]
public void ShouldDetectPng()
{
byte[] pngHeader = new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(pngHeader);
Assert.AreEqual("png", format);
}

[TestMethod]
public void ShouldDetectTiffLittleEndian()
{
byte[] tiffHeader = new byte[] { 73, 73, 42, 0 }; // II followed by 2A 00
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(tiffHeader);
Assert.AreEqual("tiff", format);
}

[TestMethod]
public void ShouldDetectTiffBigEndian()
{
byte[] tiffHeader = new byte[] { 77, 77, 0, 42 }; // MM followed by 00 2
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(tiffHeader);
Assert.AreEqual("tiff", format);
}

[TestMethod]
public void ShouldDetectJpegStandard()
{
byte[] jpegHeader = new byte[] { 255, 216, 255, 224 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(jpegHeader);
Assert.AreEqual("jpeg", format);
}

[TestMethod]
public void ShouldDetectJpegCanon()
{
byte[] jpegHeader = new byte[] { 255, 216, 255, 225 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(jpegHeader);
Assert.AreEqual("jpeg", format);
}

[TestMethod]
public void ShouldDetectJpegWithSPIFF()
{
byte[] jpegHeader = new byte[] { 255, 216, 255, 232 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(jpegHeader);
Assert.AreEqual("jpeg", format);
}

[TestMethod]
public void ShouldDetectJpegWithAdobeMarker()
{
byte[] jpegHeader = new byte[] { 255, 216, 255, 239 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(jpegHeader);
Assert.AreEqual("jpeg", format);
}

[TestMethod]
public void ShouldDetectJpegWithICCProfile()
{
byte[] jpegHeader = new byte[] { 255, 216, 255, 227 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(jpegHeader);
Assert.AreEqual("jpeg", format);
}

[TestMethod]
public void ShouldDetectJpegWithIRBMetadata()
{
byte[] jpegHeader = new byte[] { 255, 216, 255, 237 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(jpegHeader);
Assert.AreEqual("jpeg", format);
}

[TestMethod]
public void ShouldDetectJpegWithQuantizationTable()
{
byte[] jpegHeader = new byte[] { 255, 216, 255, 219 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(jpegHeader);
Assert.AreEqual("jpeg", format);
}

[TestMethod]
public void ShouldDetectJpegWithPhotoshopMetadata()
{
byte[] jpegHeader = new byte[] { 255, 216, 255, 238 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(jpegHeader);
Assert.AreEqual("jpeg", format);
}

[TestMethod]
public void ShouldDetectJpegWithCanonMarker()
{
byte[] jpegHeader = new byte[] { 255, 216, 255, 226 };
var format = TestableEmbededImagesRepairTool.CallGetImageFormat(jpegHeader);
Assert.AreEqual("jpeg", format);
}

}

/// <summary>
/// Wrapper class to expose GetImageFormat from EmbededImagesRepairToolBase
/// </summary>
public class TestableEmbededImagesRepairTool : EmbededImagesRepairToolBase<TestToolOptions>
{
public TestableEmbededImagesRepairTool(IOptions<TestToolOptions> options, IServiceProvider services, ILogger<ITool> logger, ITelemetryLogger telemetry) : base(options, services, logger, telemetry)
{
}

public static string CallGetImageFormat(byte[] bytes)
{
return GetImageFormat(bytes).ToString();
}

protected override void FixEmbededImages(WorkItemData wi, string oldTfsurl, string newTfsurl, string sourcePersonalAccessToken = "")
{
throw new NotImplementedException();
}
}

public class TestToolOptions : IToolOptions
{
public ConfigurationMetadata ConfigurationMetadata => throw new NotImplementedException();

public bool Enabled { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,51 +56,60 @@ protected static HttpResponseMessage DownloadFile(HttpClient httpClient, string
/// Retrieve Image Format for a given byte array
/// </summary>
/// <param name="bytes">Image to check</param>
/// <remarks>From https://stackoverflow.com/a/9446045/1317161</remarks>
/// <returns>Image format</returns>
protected static ImageFormat GetImageFormat(byte[] bytes)
{
// see http://www.mikekunz.com/image_file_header.html
var bmp = Encoding.ASCII.GetBytes("BM"); // BMP
var gif = Encoding.ASCII.GetBytes("GIF"); // GIF
var png = new byte[] { 137, 80, 78, 71 }; // PNG
var tiff = new byte[] { 73, 73, 42 }; // TIFF
var tiff2 = new byte[] { 77, 77, 42 }; // TIFF
var jpeg = new byte[] { 255, 216, 255, 224 }; // jpeg
var jpeg2 = new byte[] { 255, 216, 255, 225 }; // jpeg canon
var jpeg3 = new byte[] { 255, 216, 255, 237 }; // jpeg
var jpeg4 = new byte[] { 255, 216, 255, 232 }; // jpeg still picture interchange file format (SPIFF)
var jpeg5 = new byte[] { 255, 216, 255, 226 }; // jpeg canon

if (bmp.SequenceEqual(bytes.Take(bmp.Length)))
return ImageFormat.bmp;

if (gif.SequenceEqual(bytes.Take(gif.Length)))
if (bytes != null && bytes.Length > 1)
{
// BMP: 42 4D
var bmp = new byte[] { 0x42, 0x4D };
if (bmp.SequenceEqual(bytes.Take(bmp.Length)))
return ImageFormat.bmp;
}

if (bytes == null || bytes.Length < 4)
return ImageFormat.unknown;

// GIF: GIF87a or GIF89a
var gif87a = System.Text.Encoding.ASCII.GetBytes("GIF87a");
var gif89a = System.Text.Encoding.ASCII.GetBytes("GIF89a");

// PNG: 89 50 4E 47 0D 0A 1A 0A
var png = new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };

// TIFF: II* or MM*
var tiffLE = new byte[] { 0x49, 0x49, 0x2A, 0x00 };
var tiffBE = new byte[] { 0x4D, 0x4D, 0x00, 0x2A };

// JPEG: FF D8
var jpegSOI = new byte[] { 0xFF, 0xD8 };

// Check GIF
if (gif87a.SequenceEqual(bytes.Take(gif87a.Length)) ||
gif89a.SequenceEqual(bytes.Take(gif89a.Length)))
return ImageFormat.gif;

// Check PNG
if (png.SequenceEqual(bytes.Take(png.Length)))
return ImageFormat.png;

if (tiff.SequenceEqual(bytes.Take(tiff.Length)))
return ImageFormat.tiff;

if (tiff2.SequenceEqual(bytes.Take(tiff2.Length)))
// Check TIFF
if (tiffLE.SequenceEqual(bytes.Take(tiffLE.Length)) ||
tiffBE.SequenceEqual(bytes.Take(tiffBE.Length)))
return ImageFormat.tiff;

if (jpeg.SequenceEqual(bytes.Take(jpeg.Length)))
// Check JPEG
if (jpegSOI.SequenceEqual(bytes.Take(jpegSOI.Length)))
return ImageFormat.jpeg;

if (jpeg2.SequenceEqual(bytes.Take(jpeg2.Length)))
return ImageFormat.jpeg;
var text = Encoding.UTF8.GetString(bytes);
text = text.TrimStart();

if (jpeg3.SequenceEqual(bytes.Take(jpeg3.Length)))
return ImageFormat.jpeg;

if (jpeg4.SequenceEqual(bytes.Take(jpeg4.Length)))
return ImageFormat.jpeg;

if (jpeg5.SequenceEqual(bytes.Take(jpeg5.Length)))
return ImageFormat.jpeg;
if (text.StartsWith("<svg", StringComparison.OrdinalIgnoreCase) ||
(text.StartsWith("<?xml", StringComparison.OrdinalIgnoreCase) && text.Contains("<svg")))
{
return ImageFormat.svg;
}

return ImageFormat.unknown;
}
Expand Down Expand Up @@ -130,7 +139,8 @@ protected enum ImageFormat
gif,
png,
tiff,
jpeg
jpeg,
svg
}
}
}
Loading