Skip to content

Commit dad8ab6

Browse files
committed
Add project files.
1 parent 6a0a7a6 commit dad8ab6

File tree

9 files changed

+599
-0
lines changed

9 files changed

+599
-0
lines changed

edds2png.sln

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.8.34330.188
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "edds2png", "edds2png\edds2png.csproj", "{8474C64F-E0B6-4325-B4B1-D38189307EAF}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{8474C64F-E0B6-4325-B4B1-D38189307EAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{8474C64F-E0B6-4325-B4B1-D38189307EAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{8474C64F-E0B6-4325-B4B1-D38189307EAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{8474C64F-E0B6-4325-B4B1-D38189307EAF}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {4B5C2DF4-918F-424D-A103-32FF6BB36699}
24+
EndGlobalSection
25+
EndGlobal

edds2png/App.config

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
5+
</startup>
6+
<runtime>
7+
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
8+
<dependentAssembly>
9+
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
10+
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
11+
</dependentAssembly>
12+
</assemblyBinding>
13+
</runtime>
14+
</configuration>

edds2png/BulkConverter.cs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
using K4os.Compression.LZ4.Encoders;
2+
using Pfim;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Drawing;
6+
using System.Drawing.Imaging;
7+
using System.IO;
8+
using System.Linq;
9+
using System.Runtime.InteropServices;
10+
using System.Text;
11+
12+
namespace edds2png
13+
{
14+
internal class BulkConverter
15+
{
16+
private readonly List<string> _imagePaths;
17+
18+
public BulkConverter()
19+
{
20+
_imagePaths = new List<string>();
21+
}
22+
23+
public void Add(string path)
24+
{
25+
if (string.IsNullOrEmpty(path))
26+
{
27+
return;
28+
}
29+
30+
if (!path.EndsWith(".edds", StringComparison.OrdinalIgnoreCase))
31+
{
32+
return;
33+
}
34+
35+
_imagePaths.Add(path);
36+
}
37+
38+
public void Process()
39+
{
40+
List<Exception> conversionExceptions = new List<Exception>();
41+
foreach (var imagePath in _imagePaths.AsEnumerable())
42+
{
43+
try
44+
{
45+
string fullPath = Path.GetFullPath(imagePath);
46+
Convert(fullPath);
47+
48+
Console.WriteLine($"{fullPath} -> {Path.ChangeExtension(fullPath, ".png")}");
49+
}
50+
catch (Exception inner)
51+
{
52+
conversionExceptions.Add(inner);
53+
}
54+
}
55+
56+
if (conversionExceptions.Count != 0)
57+
{
58+
throw new AggregateException(conversionExceptions);
59+
}
60+
}
61+
62+
public bool CanProcess()
63+
{
64+
return _imagePaths.Count != 0;
65+
}
66+
67+
private static unsafe void Convert(string imagePath)
68+
{
69+
using (var stream = DecompressEDDS(imagePath))
70+
{
71+
using (var image = Pfimage.FromStream(stream))
72+
{
73+
PixelFormat format;
74+
switch (image.Format)
75+
{
76+
case Pfim.ImageFormat.Rgba32:
77+
{
78+
format = PixelFormat.Format32bppArgb;
79+
break;
80+
}
81+
default:
82+
{
83+
throw new NotImplementedException();
84+
}
85+
}
86+
87+
88+
var handle = GCHandle.Alloc(image.Data, GCHandleType.Pinned);
89+
try
90+
{
91+
var data = Marshal.UnsafeAddrOfPinnedArrayElement(image.Data, 0);
92+
var bitmap = new Bitmap(image.Width, image.Height, image.Stride, format, data);
93+
bitmap.Save(Path.ChangeExtension(imagePath, ".png"), System.Drawing.Imaging.ImageFormat.Png);
94+
}
95+
finally
96+
{
97+
handle.Free();
98+
}
99+
}
100+
}
101+
}
102+
103+
private static MemoryStream DecompressEDDS(string imagePath)
104+
{
105+
List<int> copyBlocks = new List<int>();
106+
List<int> lz4Blocks = new List<int>();
107+
List<byte> decodedBlocks = new List<byte>();
108+
109+
void FindBlocks(BinaryReader reader)
110+
{
111+
while (true)
112+
{
113+
byte[] blocks = reader.ReadBytes(4);
114+
char[] dd = Encoding.UTF8.GetChars(blocks);
115+
116+
string block = new string(dd);
117+
int size = reader.ReadInt32();
118+
119+
switch (block)
120+
{
121+
case "COPY": copyBlocks.Add(size); break;
122+
case "LZ4 ": lz4Blocks.Add(size); break;
123+
default: reader.BaseStream.Seek(-8, SeekOrigin.Current); return;
124+
}
125+
}
126+
}
127+
128+
using (var reader = new BinaryReader(File.Open(imagePath, FileMode.Open)))
129+
{
130+
byte[] dds_header = reader.ReadBytes(128);
131+
byte[] dds_header_dx10 = null;
132+
133+
if (dds_header[84] == 'D' && dds_header[85] == 'X' && dds_header[86] == '1' && dds_header[87] == '0')
134+
{
135+
dds_header_dx10 = reader.ReadBytes(20);
136+
}
137+
138+
FindBlocks(reader);
139+
140+
foreach (int count in copyBlocks)
141+
{
142+
byte[] buff = reader.ReadBytes(count);
143+
decodedBlocks.InsertRange(0, buff);
144+
}
145+
146+
foreach (int Length in lz4Blocks)
147+
{
148+
LZ4ChainDecoder lz4ChainDecoder = new LZ4ChainDecoder(65536, 0);
149+
uint size = reader.ReadUInt32();
150+
byte[] target = new byte[size];
151+
152+
int num = 0;
153+
int count1 = 0;
154+
int idx = 0;
155+
for (; num < Length - 4; num += count1 + 4)
156+
{
157+
count1 = reader.ReadInt32() & int.MaxValue;
158+
byte[] numArray = reader.ReadBytes(count1);
159+
byte[] buffer = new byte[65536];
160+
LZ4EncoderExtensions.DecodeAndDrain(lz4ChainDecoder, numArray, 0, count1, buffer, 0, 65536, out int count2);
161+
162+
Array.Copy(buffer, 0, target, idx, count2);
163+
idx += count2;
164+
}
165+
166+
decodedBlocks.InsertRange(0, target);
167+
}
168+
169+
if (dds_header_dx10 != null)
170+
{
171+
decodedBlocks.InsertRange(0, dds_header_dx10);
172+
}
173+
174+
decodedBlocks.InsertRange(0, dds_header);
175+
byte[] final = decodedBlocks.ToArray();
176+
177+
MemoryStream stream = new MemoryStream();
178+
stream.Write(final, 0, final.Length);
179+
stream.Position = 0;
180+
181+
return stream;
182+
}
183+
}
184+
}
185+
}

edds2png/FodyWeavers.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
2+
<Costura />
3+
</Weavers>

edds2png/Program.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.IO;
3+
4+
namespace edds2png
5+
{
6+
internal class Program
7+
{
8+
static void Main(string[] args)
9+
{
10+
Console.Title = "edds2png";
11+
var converter = new BulkConverter();
12+
13+
foreach (var arg in args)
14+
{
15+
if (Directory.Exists(arg))
16+
{
17+
var files = Directory.EnumerateFiles(arg, "*.edds", SearchOption.TopDirectoryOnly);
18+
foreach (var file in files)
19+
{
20+
converter.Add(file);
21+
}
22+
}
23+
else
24+
{
25+
converter.Add(arg);
26+
}
27+
}
28+
29+
if (converter.CanProcess())
30+
{
31+
converter.Process();
32+
33+
Console.Write(Environment.NewLine);
34+
Console.Write("Press ENTER to exit...");
35+
while (Console.ReadKey(true).Key != ConsoleKey.Enter) { };
36+
}
37+
}
38+
}
39+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Reflection;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("edds2png")]
9+
[assembly: AssemblyDescription("Converts Bohemia edds to png")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("Wardog (wrdg)")]
12+
[assembly: AssemblyProduct("edds2png")]
13+
[assembly: AssemblyCopyright("Copyright © 2024")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("8474c64f-e0b6-4325-b4b1-d38189307eaf")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("2024.2.10.0410")]

0 commit comments

Comments
 (0)