mirror of https://github.com/SixLabors/ImageSharp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
5.4 KiB
145 lines
5.4 KiB
// Copyright (c) Six Labors.
|
|
// Licensed under the Apache License, Version 2.0.
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Numerics;
|
|
using System.Runtime.InteropServices;
|
|
|
|
using SixLabors.ImageSharp.Formats.Jpeg.Components;
|
|
|
|
namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
|
|
{
|
|
/// <summary>
|
|
/// Utilities to read raw libjpeg data for reference conversion.
|
|
/// </summary>
|
|
internal static partial class LibJpegTools
|
|
{
|
|
public static (double total, double average) CalculateDifference(ComponentData expected, ComponentData actual)
|
|
{
|
|
BigInteger totalDiff = 0;
|
|
if (actual.WidthInBlocks < expected.WidthInBlocks)
|
|
{
|
|
throw new Exception("actual.WidthInBlocks < expected.WidthInBlocks");
|
|
}
|
|
|
|
if (actual.HeightInBlocks < expected.HeightInBlocks)
|
|
{
|
|
throw new Exception("actual.HeightInBlocks < expected.HeightInBlocks");
|
|
}
|
|
|
|
int w = expected.WidthInBlocks;
|
|
int h = expected.HeightInBlocks;
|
|
for (int y = 0; y < h; y++)
|
|
{
|
|
for (int x = 0; x < w; x++)
|
|
{
|
|
Block8x8 aa = expected.SpectralBlocks[x, y];
|
|
Block8x8 bb = actual.SpectralBlocks[x, y];
|
|
|
|
long diff = Block8x8.TotalDifference(ref aa, ref bb);
|
|
totalDiff += diff;
|
|
}
|
|
}
|
|
|
|
int count = w * h;
|
|
double total = (double)totalDiff;
|
|
double average = (double)totalDiff / (count * Block8x8.Size);
|
|
return (total, average);
|
|
}
|
|
|
|
private static string DumpToolFullPath => Path.Combine(
|
|
TestEnvironment.ToolsDirectoryFullPath,
|
|
@"jpeg\dump-jpeg-coeffs.exe");
|
|
|
|
/// <summary>
|
|
/// Executes 'dump-jpeg-coeffs.exe' for the given jpeg image file, saving the libjpeg spectral data into 'destFile'. Windows only!
|
|
/// See:
|
|
/// <see>
|
|
/// <cref>https://github.com/SixLabors/Imagesharp.Tests.Images/blob/master/tools/jpeg/README.md</cref>
|
|
/// </see>
|
|
/// </summary>
|
|
public static void RunDumpJpegCoeffsTool(string sourceFile, string destFile)
|
|
{
|
|
if (!TestEnvironment.IsWindows)
|
|
{
|
|
throw new InvalidOperationException("Can't run dump-jpeg-coeffs.exe in non-Windows environment. Skip this test on Linux/Unix!");
|
|
}
|
|
|
|
string args = $@"""{sourceFile}"" ""{destFile}""";
|
|
var process = new Process
|
|
{
|
|
StartInfo =
|
|
{
|
|
FileName = DumpToolFullPath,
|
|
Arguments = args,
|
|
WindowStyle = ProcessWindowStyle.Hidden
|
|
}
|
|
};
|
|
process.Start();
|
|
process.WaitForExit();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extract libjpeg <see cref="SpectralData"/> from the given jpg file with 'dump-jpeg-coeffs.exe'. Windows only!
|
|
/// See:
|
|
/// https://github.com/SixLabors/Imagesharp.Tests.Images/blob/master/tools/jpeg/README.md
|
|
/// </summary>
|
|
public static SpectralData ExtractSpectralData(string inputFile)
|
|
{
|
|
TestFile testFile = TestFile.Create(inputFile);
|
|
|
|
string outDir = TestEnvironment.CreateOutputDirectory(".Temp", "JpegCoeffs");
|
|
string fn = $"{Path.GetFileName(inputFile)}-{new Random().Next(1000)}.dctcoeffs";
|
|
string coeffFileFullPath = Path.Combine(outDir, fn);
|
|
|
|
try
|
|
{
|
|
RunDumpJpegCoeffsTool(testFile.FullPath, coeffFileFullPath);
|
|
|
|
using (var dumpStream = new FileStream(coeffFileFullPath, FileMode.Open))
|
|
using (var rdr = new BinaryReader(dumpStream))
|
|
{
|
|
int componentCount = rdr.ReadInt16();
|
|
var result = new ComponentData[componentCount];
|
|
|
|
for (int i = 0; i < componentCount; i++)
|
|
{
|
|
int widthInBlocks = rdr.ReadInt16();
|
|
int heightInBlocks = rdr.ReadInt16();
|
|
var resultComponent = new ComponentData(widthInBlocks, heightInBlocks, i);
|
|
result[i] = resultComponent;
|
|
}
|
|
|
|
var buffer = new byte[64 * sizeof(short)];
|
|
|
|
for (int i = 0; i < result.Length; i++)
|
|
{
|
|
ComponentData c = result[i];
|
|
|
|
for (int y = 0; y < c.HeightInBlocks; y++)
|
|
{
|
|
for (int x = 0; x < c.WidthInBlocks; x++)
|
|
{
|
|
rdr.Read(buffer, 0, buffer.Length);
|
|
|
|
short[] block = MemoryMarshal.Cast<byte, short>(buffer.AsSpan()).ToArray();
|
|
c.MakeBlock(block, y, x);
|
|
}
|
|
}
|
|
}
|
|
|
|
return new SpectralData(result);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (File.Exists(coeffFileFullPath))
|
|
{
|
|
File.Delete(coeffFileFullPath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|