mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
WIP
This commit is contained in:
parent
abd142623f
commit
6706d5bfb6
@ -12,10 +12,11 @@ namespace Wabbajack.ImageHashing
|
|||||||
{
|
{
|
||||||
public class DDSImage
|
public class DDSImage
|
||||||
{
|
{
|
||||||
private DDSImage(ScratchImage img, TexMetadata metadata)
|
private DDSImage(ScratchImage img, TexMetadata metadata, Extension ext)
|
||||||
{
|
{
|
||||||
_image = img;
|
_image = img;
|
||||||
_metaData = metadata;
|
_metaData = metadata;
|
||||||
|
_extension = ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Extension DDSExtension = new(".dds");
|
private static Extension DDSExtension = new(".dds");
|
||||||
@ -29,7 +30,7 @@ namespace Wabbajack.ImageHashing
|
|||||||
|
|
||||||
var img = TexHelper.Instance.LoadFromDDSFile(file.ToString(), DDS_FLAGS.NONE);
|
var img = TexHelper.Instance.LoadFromDDSFile(file.ToString(), DDS_FLAGS.NONE);
|
||||||
|
|
||||||
return new DDSImage(img, img.GetMetadata());
|
return new DDSImage(img, img.GetMetadata(), new Extension(".dds"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DDSImage FromDDSMemory(byte[] data)
|
public static DDSImage FromDDSMemory(byte[] data)
|
||||||
@ -39,7 +40,7 @@ namespace Wabbajack.ImageHashing
|
|||||||
fixed (byte* ptr = data)
|
fixed (byte* ptr = data)
|
||||||
{
|
{
|
||||||
var img = TexHelper.Instance.LoadFromDDSMemory((IntPtr)ptr, data.Length, DDS_FLAGS.NONE);
|
var img = TexHelper.Instance.LoadFromDDSMemory((IntPtr)ptr, data.Length, DDS_FLAGS.NONE);
|
||||||
return new DDSImage(img, img.GetMetadata());
|
return new DDSImage(img, img.GetMetadata(), new Extension(".dds"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,7 +52,7 @@ namespace Wabbajack.ImageHashing
|
|||||||
fixed (byte* ptr = data)
|
fixed (byte* ptr = data)
|
||||||
{
|
{
|
||||||
var img = TexHelper.Instance.LoadFromTGAMemory((IntPtr)ptr, data.Length);
|
var img = TexHelper.Instance.LoadFromTGAMemory((IntPtr)ptr, data.Length);
|
||||||
return new DDSImage(img, img.GetMetadata());
|
return new DDSImage(img, img.GetMetadata(), new Extension(".tga"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,11 +96,24 @@ namespace Wabbajack.ImageHashing
|
|||||||
DXGI_FORMAT.BC7_UNORM_SRGB,
|
DXGI_FORMAT.BC7_UNORM_SRGB,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private Extension _extension;
|
||||||
|
|
||||||
|
public ImageState ImageState()
|
||||||
|
{
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
Width = _metaData.Width,
|
||||||
|
Height = _metaData.Height,
|
||||||
|
PerceptualHash = PerceptionHash()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public PHash PerceptionHash()
|
public PHash PerceptionHash()
|
||||||
{
|
{
|
||||||
ScratchImage? resized = default;
|
ScratchImage? resized = default;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// First we resize the image, so that changes due to image scaling matter less in the final hash
|
||||||
if (CompressedTypes.Contains(_metaData.Format))
|
if (CompressedTypes.Contains(_metaData.Format))
|
||||||
{
|
{
|
||||||
using var decompressed = _image.Decompress(DXGI_FORMAT.UNKNOWN);
|
using var decompressed = _image.Decompress(DXGI_FORMAT.UNKNOWN);
|
||||||
@ -109,8 +123,7 @@ namespace Wabbajack.ImageHashing
|
|||||||
{
|
{
|
||||||
resized = _image.Resize(512, 512, TEX_FILTER_FLAGS.DEFAULT);
|
resized = _image.Resize(512, 512, TEX_FILTER_FLAGS.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = new List<(int, int)>();
|
|
||||||
var image = new byte[512 * 512];
|
var image = new byte[512 * 512];
|
||||||
|
|
||||||
unsafe void EvaluatePixels(IntPtr pixels, IntPtr width, IntPtr line)
|
unsafe void EvaluatePixels(IntPtr pixels, IntPtr width, IntPtr line)
|
||||||
@ -121,7 +134,6 @@ namespace Wabbajack.ImageHashing
|
|||||||
if (widthV != 512) return;
|
if (widthV != 512) return;
|
||||||
|
|
||||||
var y = line.ToInt32();
|
var y = line.ToInt32();
|
||||||
data.Add((widthV, y));
|
|
||||||
|
|
||||||
for (int i = 0; i < widthV; i++)
|
for (int i = 0; i < widthV; i++)
|
||||||
{
|
{
|
||||||
|
33
Wabbajack.ImageHashing/ImageState.cs
Normal file
33
Wabbajack.ImageHashing/ImageState.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System.IO;
|
||||||
|
using DirectXTexNet;
|
||||||
|
using Wabbajack.Common;
|
||||||
|
|
||||||
|
namespace Wabbajack.ImageHashing
|
||||||
|
{
|
||||||
|
public class ImageState
|
||||||
|
{
|
||||||
|
public int Width { get; set; }
|
||||||
|
public int Height { get; set; }
|
||||||
|
public DXGI_FORMAT Format { get; set; }
|
||||||
|
public PHash PerceptualHash { get; set; }
|
||||||
|
|
||||||
|
public static ImageState Read(BinaryReader br)
|
||||||
|
{
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
Width = br.ReadUInt16(),
|
||||||
|
Height = br.ReadUInt16(),
|
||||||
|
Format = (DXGI_FORMAT)br.ReadByte(),
|
||||||
|
PerceptualHash = PHash.Read(br)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(BinaryWriter bw)
|
||||||
|
{
|
||||||
|
bw.Write((ushort)Width);
|
||||||
|
bw.Write((ushort)Height);
|
||||||
|
bw.Write((byte)Format);
|
||||||
|
PerceptualHash.Write(bw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,12 +11,24 @@ namespace Wabbajack.ImageHashing
|
|||||||
{
|
{
|
||||||
private const int SIZE = 40;
|
private const int SIZE = 40;
|
||||||
private readonly byte[] _data;
|
private readonly byte[] _data;
|
||||||
|
private readonly int _hash;
|
||||||
|
|
||||||
private PHash(byte[]? data)
|
private PHash(byte[] data)
|
||||||
{
|
{
|
||||||
_data = data ?? new byte[SIZE];
|
_data = data;
|
||||||
if (_data.Length != SIZE)
|
if (_data.Length != SIZE)
|
||||||
throw new DataException();
|
throw new DataException();
|
||||||
|
|
||||||
|
long h = 0;
|
||||||
|
h |= _data[0];
|
||||||
|
h <<= 8;
|
||||||
|
h |= _data[1];
|
||||||
|
h <<= 8;
|
||||||
|
h |= _data[2];
|
||||||
|
h <<= 8;
|
||||||
|
h |= _data[3];
|
||||||
|
h <<= 8;
|
||||||
|
_hash = (int)h;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PHash FromBase64(string base64)
|
public static PHash FromBase64(string base64)
|
||||||
@ -34,7 +46,10 @@ namespace Wabbajack.ImageHashing
|
|||||||
|
|
||||||
public void Write(BinaryWriter br)
|
public void Write(BinaryWriter br)
|
||||||
{
|
{
|
||||||
br.Write((_data?.Length ?? 0) == 0 ? new byte[SIZE] : _data);
|
if (_hash == 0)
|
||||||
|
br.Write(new byte[SIZE]);
|
||||||
|
else
|
||||||
|
br.Write(_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PHash FromDigest(Digest digest)
|
public static PHash FromDigest(Digest digest)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -18,7 +19,7 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
public IPath Name { get; set; }
|
public IPath Name { get; set; }
|
||||||
public Hash Hash { get; set; }
|
public Hash Hash { get; set; }
|
||||||
|
|
||||||
public PHash PerceptualHash { get; set; }
|
public ImageState? ImageState { get; set; }
|
||||||
public long Size { get; set; }
|
public long Size { get; set; }
|
||||||
public List<IndexedVirtualFile> Children { get; set; } = new();
|
public List<IndexedVirtualFile> Children { get; set; } = new();
|
||||||
|
|
||||||
@ -26,7 +27,15 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
{
|
{
|
||||||
bw.Write(Name.ToString());
|
bw.Write(Name.ToString());
|
||||||
bw.Write((ulong)Hash);
|
bw.Write((ulong)Hash);
|
||||||
PerceptualHash.Write(bw);
|
|
||||||
|
if (ImageState == null)
|
||||||
|
bw.Write(false);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bw.Write(true);
|
||||||
|
ImageState.Write(bw);
|
||||||
|
}
|
||||||
|
|
||||||
bw.Write(Size);
|
bw.Write(Size);
|
||||||
bw.Write(Children.Count);
|
bw.Write(Children.Count);
|
||||||
foreach (var file in Children)
|
foreach (var file in Children)
|
||||||
@ -35,7 +44,8 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
|
|
||||||
public void Write(Stream s)
|
public void Write(Stream s)
|
||||||
{
|
{
|
||||||
using var bw = new BinaryWriter(s, Encoding.UTF8, true);
|
using var cs = new GZipStream(s, CompressionLevel.Optimal , true);
|
||||||
|
using var bw = new BinaryWriter(cs, Encoding.UTF8, true);
|
||||||
bw.Write(Size);
|
bw.Write(Size);
|
||||||
bw.Write(Children.Count);
|
bw.Write(Children.Count);
|
||||||
foreach (var file in Children)
|
foreach (var file in Children)
|
||||||
@ -48,9 +58,13 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
{
|
{
|
||||||
Name = (RelativePath)br.ReadString(),
|
Name = (RelativePath)br.ReadString(),
|
||||||
Hash = Hash.FromULong(br.ReadUInt64()),
|
Hash = Hash.FromULong(br.ReadUInt64()),
|
||||||
PerceptualHash = PHash.Read(br),
|
|
||||||
Size = br.ReadInt64(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (br.ReadBoolean())
|
||||||
|
ivf.ImageState = ImageState.Read(br);
|
||||||
|
|
||||||
|
ivf.Size = br.ReadInt64();
|
||||||
|
|
||||||
var lst = new List<IndexedVirtualFile>();
|
var lst = new List<IndexedVirtualFile>();
|
||||||
ivf.Children = lst;
|
ivf.Children = lst;
|
||||||
var count = br.ReadInt32();
|
var count = br.ReadInt32();
|
||||||
@ -64,7 +78,8 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
|
|
||||||
public static IndexedVirtualFile Read(Stream s)
|
public static IndexedVirtualFile Read(Stream s)
|
||||||
{
|
{
|
||||||
using var br = new BinaryReader(s);
|
using var cs = new GZipStream(s, CompressionMode.Decompress, true);
|
||||||
|
using var br = new BinaryReader(cs);
|
||||||
var ivf = new IndexedVirtualFile
|
var ivf = new IndexedVirtualFile
|
||||||
{
|
{
|
||||||
Size = br.ReadInt64(),
|
Size = br.ReadInt64(),
|
||||||
|
Loading…
Reference in New Issue
Block a user