Skip to content

Commit

Permalink
Add project files.
Browse files Browse the repository at this point in the history
  • Loading branch information
wrdg committed Feb 10, 2024
1 parent 6a0a7a6 commit dad8ab6
Show file tree
Hide file tree
Showing 9 changed files with 599 additions and 0 deletions.
25 changes: 25 additions & 0 deletions edds2png.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "edds2png", "edds2png\edds2png.csproj", "{8474C64F-E0B6-4325-B4B1-D38189307EAF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8474C64F-E0B6-4325-B4B1-D38189307EAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8474C64F-E0B6-4325-B4B1-D38189307EAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8474C64F-E0B6-4325-B4B1-D38189307EAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8474C64F-E0B6-4325-B4B1-D38189307EAF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4B5C2DF4-918F-424D-A103-32FF6BB36699}
EndGlobalSection
EndGlobal
14 changes: 14 additions & 0 deletions edds2png/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
185 changes: 185 additions & 0 deletions edds2png/BulkConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
using K4os.Compression.LZ4.Encoders;
using Pfim;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace edds2png
{
internal class BulkConverter
{
private readonly List<string> _imagePaths;

public BulkConverter()
{
_imagePaths = new List<string>();
}

public void Add(string path)
{
if (string.IsNullOrEmpty(path))
{
return;
}

if (!path.EndsWith(".edds", StringComparison.OrdinalIgnoreCase))
{
return;
}

_imagePaths.Add(path);
}

public void Process()
{
List<Exception> conversionExceptions = new List<Exception>();
foreach (var imagePath in _imagePaths.AsEnumerable())
{
try
{
string fullPath = Path.GetFullPath(imagePath);
Convert(fullPath);

Console.WriteLine($"{fullPath} -> {Path.ChangeExtension(fullPath, ".png")}");
}
catch (Exception inner)
{
conversionExceptions.Add(inner);
}
}

if (conversionExceptions.Count != 0)
{
throw new AggregateException(conversionExceptions);
}
}

public bool CanProcess()
{
return _imagePaths.Count != 0;
}

private static unsafe void Convert(string imagePath)
{
using (var stream = DecompressEDDS(imagePath))
{
using (var image = Pfimage.FromStream(stream))
{
PixelFormat format;
switch (image.Format)
{
case Pfim.ImageFormat.Rgba32:
{
format = PixelFormat.Format32bppArgb;
break;
}
default:
{
throw new NotImplementedException();
}
}


var handle = GCHandle.Alloc(image.Data, GCHandleType.Pinned);
try
{
var data = Marshal.UnsafeAddrOfPinnedArrayElement(image.Data, 0);
var bitmap = new Bitmap(image.Width, image.Height, image.Stride, format, data);
bitmap.Save(Path.ChangeExtension(imagePath, ".png"), System.Drawing.Imaging.ImageFormat.Png);
}
finally
{
handle.Free();
}
}
}
}

private static MemoryStream DecompressEDDS(string imagePath)
{
List<int> copyBlocks = new List<int>();
List<int> lz4Blocks = new List<int>();
List<byte> decodedBlocks = new List<byte>();

void FindBlocks(BinaryReader reader)
{
while (true)
{
byte[] blocks = reader.ReadBytes(4);
char[] dd = Encoding.UTF8.GetChars(blocks);

string block = new string(dd);
int size = reader.ReadInt32();

switch (block)
{
case "COPY": copyBlocks.Add(size); break;
case "LZ4 ": lz4Blocks.Add(size); break;
default: reader.BaseStream.Seek(-8, SeekOrigin.Current); return;
}
}
}

using (var reader = new BinaryReader(File.Open(imagePath, FileMode.Open)))
{
byte[] dds_header = reader.ReadBytes(128);
byte[] dds_header_dx10 = null;

if (dds_header[84] == 'D' && dds_header[85] == 'X' && dds_header[86] == '1' && dds_header[87] == '0')
{
dds_header_dx10 = reader.ReadBytes(20);
}

FindBlocks(reader);

foreach (int count in copyBlocks)
{
byte[] buff = reader.ReadBytes(count);
decodedBlocks.InsertRange(0, buff);
}

foreach (int Length in lz4Blocks)
{
LZ4ChainDecoder lz4ChainDecoder = new LZ4ChainDecoder(65536, 0);
uint size = reader.ReadUInt32();
byte[] target = new byte[size];

int num = 0;
int count1 = 0;
int idx = 0;
for (; num < Length - 4; num += count1 + 4)
{
count1 = reader.ReadInt32() & int.MaxValue;
byte[] numArray = reader.ReadBytes(count1);
byte[] buffer = new byte[65536];
LZ4EncoderExtensions.DecodeAndDrain(lz4ChainDecoder, numArray, 0, count1, buffer, 0, 65536, out int count2);

Array.Copy(buffer, 0, target, idx, count2);
idx += count2;
}

decodedBlocks.InsertRange(0, target);
}

if (dds_header_dx10 != null)
{
decodedBlocks.InsertRange(0, dds_header_dx10);
}

decodedBlocks.InsertRange(0, dds_header);
byte[] final = decodedBlocks.ToArray();

MemoryStream stream = new MemoryStream();
stream.Write(final, 0, final.Length);
stream.Position = 0;

return stream;
}
}
}
}
3 changes: 3 additions & 0 deletions edds2png/FodyWeavers.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>
39 changes: 39 additions & 0 deletions edds2png/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.IO;

namespace edds2png
{
internal class Program
{
static void Main(string[] args)
{
Console.Title = "edds2png";
var converter = new BulkConverter();

foreach (var arg in args)
{
if (Directory.Exists(arg))
{
var files = Directory.EnumerateFiles(arg, "*.edds", SearchOption.TopDirectoryOnly);
foreach (var file in files)
{
converter.Add(file);
}
}
else
{
converter.Add(arg);
}
}

if (converter.CanProcess())
{
converter.Process();

Console.Write(Environment.NewLine);
Console.Write("Press ENTER to exit...");
while (Console.ReadKey(true).Key != ConsoleKey.Enter) { };
}
}
}
}
35 changes: 35 additions & 0 deletions edds2png/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("edds2png")]
[assembly: AssemblyDescription("Converts Bohemia edds to png")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Wardog (wrdg)")]
[assembly: AssemblyProduct("edds2png")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8474c64f-e0b6-4325-b4b1-d38189307eaf")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2024.2.10.0410")]
Loading

0 comments on commit dad8ab6

Please sign in to comment.