Skip to content

Commit 76d4584

Browse files
Version 1.0.2.0
Added new option to premultiply alpha when converting to XNB (now on by default).
1 parent 72b93bf commit 76d4584

22 files changed

+191
-63
lines changed

Readme.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88

99
A combination tool for managing Terraria content resources. Convert, extract, backup, and restore. The unofficial sequel to TExtract.
1010

11-
![Window Preview](http://i.imgur.com/oTuVrGQ.png)
11+
![Window Preview](https://i.imgur.com/oTuVrGQ.png)
1212

13-
### [Wiki](https://github.com/trigger-death/TConvert/wiki) | [Credits](https://github.com/trigger-death/TConvert/wiki/Credits) | [Image Album](http://imgur.com/a/QaoPd)
13+
### [Wiki](https://github.com/trigger-death/TConvert/wiki) | [Credits](https://github.com/trigger-death/TConvert/wiki/Credits) | [Image Album](https://imgur.com/a/QaoPd)
1414

1515
### [![Get TConvert](http://i.imgur.com/4BGRFF0.png)](https://github.com/trigger-death/TConvert/releases/latest)
1616

1717
## About
1818

1919
* **Created By:** Robert Jordan
20-
* **Version:** 1.0.1.0
20+
* **Version:** 1.0.2.0
2121
* **Language:** C#, WPF
2222

2323
## Requirements for Running

TConvert/App.config

+3
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@
9898
<setting name="ExtractAllowFonts" serializeAs="String">
9999
<value>True</value>
100100
</setting>
101+
<setting name="PremultiplyAlpha" serializeAs="String">
102+
<value>True</value>
103+
</setting>
101104
</TConvert.Properties.Settings>
102105
</userSettings>
103106
</configuration>

TConvert/App.xaml.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ private Assembly OnResolveAssemblies(object sender, ResolveEventArgs args) {
4141

4242
string path = assemblyName.Name + ".dll";
4343
if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) {
44-
path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);
44+
path = string.Format(@"{0}\{1}", assemblyName.CultureInfo, path);
4545
}
4646

4747
using (Stream stream = executingAssembly.GetManifestResourceStream(path)) {

TConvert/CommandLine.cs

+27-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ private enum ArgTypes {
4040
//AutoCloseDef= 0x4000,
4141
//KeepOpenDef = 0x8000,
4242
Compress = 0x10000,
43-
DontCompress= 0x20000
43+
DontCompress= 0x20000,
44+
Premultiply = 0x40000,
45+
DontPremultiply = 0x80000,
4446
}
4547

4648
/**<summary>Information about a command line option.</summary>*/
@@ -96,6 +98,8 @@ public string OptionsToString() {
9698

9799
{ ArgTypes.Compress,new OptionInfo(ProcessCompress, "Compress", "Images will be compressed.", null, "-ic", "--compress") },
98100
{ ArgTypes.DontCompress,new OptionInfo(ProcessDontCompress, "Don't Compress", "Images will not be compressed.", null, "-dc", "--dont-compress") },
101+
{ ArgTypes.Premultiply, new OptionInfo(ProcessPremultiply, "Premultiply", "RGB will be multiplied by alpha.", null, "-pr", "--premult") },
102+
{ ArgTypes.DontPremultiply, new OptionInfo(ProcessDontPremultiply, "Don't Premultiply", "RGB will not be modified.", null, "-dp", "--dont-premult") },
99103
};
100104

101105
#endregion
@@ -124,6 +128,8 @@ public string OptionsToString() {
124128
private static bool autoClose = Settings.Default.AutoCloseCmdProgress;
125129
/**<summary>True if images are compressed.</summary>*/
126130
private static bool compress = Settings.Default.CompressImages && XCompress.IsAvailable;
131+
/**<summary>True if alpha is premultiplied.</summary>*/
132+
private static bool premultiply = Settings.Default.PremultiplyAlpha;
127133
/**<summary>True if a sound is played upon completion.</summary>*/
128134
private static bool sound = Settings.Default.CompletionSound;
129135
/**<summary>True if in console-only mode.</summary>*/
@@ -335,12 +341,12 @@ public static void ProcessFiles() {
335341
});
336342
#if !(CONSOLE)
337343
if (!console) {
338-
Processing.StartProgressThread(null, "Processing Files...", autoClose, compress, sound, thread);
344+
Processing.StartProgressThread(null, "Processing Files...", autoClose, compress, sound, premultiply, thread);
339345
}
340346
else
341347
#endif
342348
{
343-
Processing.StartConsoleThread("Processing Files...", silent, compress, sound, thread);
349+
Processing.StartConsoleThread("Processing Files...", silent, compress, sound, premultiply, thread);
344350
}
345351
}
346352

@@ -554,6 +560,24 @@ private static void ProcessDontCompress() {
554560
else
555561
compress = false;
556562
}
563+
/**<summary>Processes the Premultiply option.</summary>*/
564+
private static void ProcessPremultiply() {
565+
if (passedArgs.HasFlag(ArgTypes.Premultiply))
566+
LogOptionAlreadySpecified(ArgTypes.Premultiply);
567+
if (passedArgs.HasFlag(ArgTypes.DontPremultiply))
568+
LogOptionAlreadySpecified(ArgTypes.DontPremultiply);
569+
else
570+
premultiply = true;
571+
}
572+
/**<summary>Processes the Premultiply option.</summary>*/
573+
private static void ProcessDontPremultiply() {
574+
if (passedArgs.HasFlag(ArgTypes.Premultiply))
575+
LogOptionAlreadySpecified(ArgTypes.Premultiply);
576+
if (passedArgs.HasFlag(ArgTypes.DontPremultiply))
577+
LogOptionAlreadySpecified(ArgTypes.DontPremultiply);
578+
else
579+
premultiply = false;
580+
}
557581

558582
#endregion
559583
//--------------------------------

TConvert/Config.cs

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public static class Config {
3939
public static bool CompressImages { get; set; }
4040
/**<summary>True if a sound is played on completion.</summary>*/
4141
public static bool CompletionSound { get; set; }
42+
/**<summary>True if alpha is premultiplied by default when converting to xnb.</summary>*/
43+
public static bool PremultiplyAlpha { get; set; }
4244

4345
#endregion
4446
//=========== CLASSES ============
@@ -181,6 +183,7 @@ public static void Load() {
181183
AutoCloseCmdProgress = Settings.Default.AutoCloseCmdProgress;
182184
CompressImages = Settings.Default.CompressImages && XCompress.IsAvailable;
183185
CompletionSound = Settings.Default.CompletionSound;
186+
PremultiplyAlpha = Settings.Default.PremultiplyAlpha;
184187

185188
Extract.FolderInput = Settings.Default.ExtractFolderInput;
186189
Extract.FolderOutput = Settings.Default.ExtractFolderOutput;
@@ -224,6 +227,7 @@ public static void Save() {
224227
Settings.Default.AutoCloseCmdProgress = AutoCloseCmdProgress;
225228
Settings.Default.CompressImages = CompressImages;
226229
Settings.Default.CompletionSound = CompletionSound;
230+
Settings.Default.PremultiplyAlpha = PremultiplyAlpha;
227231

228232
Settings.Default.ExtractFolderInput = Extract.FolderInput;
229233
Settings.Default.ExtractFolderOutput = Extract.FolderOutput;

TConvert/Convert/PngConverter.cs

+27-11
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public class PngConverter {
5353
#region Converting
5454

5555
/**<summary>Converts the specified input file and writes it to the output file.</summary>*/
56-
public static bool Convert(string inputFile, string outputFile, bool changeExtension, bool compressed, bool reach) {
56+
public static bool Convert(string inputFile, string outputFile, bool changeExtension, bool compressed, bool reach, bool premultiply) {
5757
if (changeExtension) {
5858
outputFile = Path.ChangeExtension(outputFile, ".xnb");
5959
}
@@ -80,11 +80,11 @@ public static bool Convert(string inputFile, string outputFile, bool changeExten
8080
}
8181
writer.Write(flagBits); // flag-bits; 00=reach, 01=hiprofile, 80=compressed, 00=uncompressed
8282
if (compressed) {
83-
WriteCompressedData(writer, bmp);
83+
WriteCompressedData(writer, bmp, premultiply);
8484
}
8585
else {
8686
writer.Write(MetadataSize + bmp.Width * bmp.Height * 4); // compressed file size
87-
WriteData(bmp, writer);
87+
WriteData(bmp, writer, premultiply);
8888
}
8989
}
9090
}
@@ -97,11 +97,11 @@ public static bool Convert(string inputFile, string outputFile, bool changeExten
9797
#region Writing
9898

9999
/**<summary>Write compressed image data.</summary>*/
100-
private static void WriteCompressedData(BinaryWriter writer, Bitmap png) {
100+
private static void WriteCompressedData(BinaryWriter writer, Bitmap png, bool premultiply) {
101101
using (MemoryStream stream = new MemoryStream()) {
102102
byte[] uncompressedData;
103103
using (BinaryWriter writer2 = new BinaryWriter(stream)) {
104-
WriteData(png, writer2);
104+
WriteData(png, writer2, premultiply);
105105
uncompressedData = stream.ToArray();
106106
}
107107
byte[] compressedData = XCompress.Compress(uncompressedData);
@@ -111,7 +111,7 @@ private static void WriteCompressedData(BinaryWriter writer, Bitmap png) {
111111
}
112112
}
113113
/**<summary>Write uncompressed image data.</summary>*/
114-
private static void WriteData(Bitmap bmp, BinaryWriter writer) {
114+
private static void WriteData(Bitmap bmp, BinaryWriter writer, bool premultiply) {
115115
writer.Write7BitEncodedInt(1); // type-reader-count
116116
writer.Write7BitEncodedString(Texture2DType); // type-reader-name
117117
writer.Write((int)0); // reader version number
@@ -130,14 +130,30 @@ private static void WriteData(Bitmap bmp, BinaryWriter writer) {
130130
}
131131
BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
132132
try {
133-
var length = bitmapData.Stride * bitmapData.Height;
133+
int length = bitmapData.Stride * bitmapData.Height;
134134
byte[] bytes = new byte[length];
135135
Marshal.Copy(bitmapData.Scan0, bytes, 0, length);
136-
// Swap the R and B channels
137136
for (int i = 0; i < bytes.Length; i += 4) {
138-
byte b = bytes[i];
139-
bytes[i] = bytes[i + 2];
140-
bytes[i + 2] = b;
137+
// Always swap red and blue channels premultiply alpha if requested
138+
int a = bytes[i + 3];
139+
if (!premultiply || a == 255) {
140+
// No premultiply necessary
141+
byte b = bytes[i];
142+
bytes[i] = bytes[i + 2];
143+
bytes[i + 2] = b;
144+
}
145+
else if (a != 0) {
146+
byte b = bytes[i];
147+
bytes[i] = (byte) (bytes[i + 2] * a / 255);
148+
bytes[i + 1] = (byte) (bytes[i + 1] * a / 255);
149+
bytes[i + 2] = (byte) (b * a / 255);
150+
}
151+
else {
152+
// alpha is zero, so just zero everything
153+
bytes[i] = 0;
154+
bytes[i + 1] = 0;
155+
bytes[i + 2] = 0;
156+
}
141157
}
142158
writer.Write(bytes);
143159
}

TConvert/Convert/WavConverter.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ public static bool Convert(string inputFile, string outputFile, bool changeExten
9797
throw new WavException("Average bytes per second number incorrect.");
9898
if (nBlockAlign != (nChannels * (wBitsPerSample / 8)))
9999
throw new WavException("Block align number incorrect.");
100-
101-
100+
102101
inputStream.Position = chunkSize;
103102

104103
format = new string(reader.ReadChars(4));

TConvert/Extract/Ffmpeg.cs

-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ public static bool Convert(string input, string output) {
6161
"-acodec pcm_s16le " +
6262
"-nostdin " +
6363
"-ab 128k " +
64-
//"-fflags +bitexact -flags:a +bitexact " +
65-
//"-metadata title=\"\" " +
6664
"-map_metadata -1 " +
6765
"-y " +
6866
"\"" + Path.GetFullPath(output) + "\"";

TConvert/MainWindow.xaml

+5
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
</MenuItem>
4545
</MenuItem>
4646
<MenuItem Header="Options">
47+
<MenuItem x:Name="menuItemPremultiply" Header="Premultiply Alpha" IsCheckable="True">
48+
<MenuItem.Icon>
49+
<Image Source="Resources/Icons/Premultiply.png"/>
50+
</MenuItem.Icon>
51+
</MenuItem>
4752
<MenuItem x:Name="menuItemCompressImages" Header="Compress Images" Click="OnCompressImagesChecked" IsCheckable="True">
4853
<MenuItem.Icon>
4954
<Image Source="Resources/Icons/Compression.png"/>

TConvert/MainWindow.xaml.cs

+12-6
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ private void LoadConfig() {
144144

145145
menuItemCompressImages.IsEnabled = XCompress.IsAvailable;
146146
menuItemCompressImages.IsChecked = Config.CompressImages;
147+
menuItemPremultiply.IsChecked = Config.PremultiplyAlpha;
147148
menuItemCompletionSound.IsChecked = Config.CompletionSound;
148149
menuItemAutoCloseProgress.IsChecked = Config.AutoCloseProgress;
149150
menuItemAutoCloseDropProgress.IsChecked = Config.AutoCloseDropProgress;
@@ -251,7 +252,7 @@ private void OnExtract(object sender, RoutedEventArgs e) {
251252
Processing.ExtractSingleFile(input, output);
252253
});
253254
}
254-
Processing.StartProgressThread(this, "Extracting...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, thread);
255+
Processing.StartProgressThread(this, "Extracting...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, Config.PremultiplyAlpha, thread);
255256
}
256257
private void OnExtractModeChanged(object sender, SelectionChangedEventArgs e) {
257258
if (!loaded)
@@ -374,7 +375,7 @@ private void OnConvert(object sender, RoutedEventArgs e) {
374375
Processing.ConvertSingleFile(input, output);
375376
});
376377
}
377-
Processing.StartProgressThread(this, "Converting...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, thread);
378+
Processing.StartProgressThread(this, "Converting...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, Config.PremultiplyAlpha, thread);
378379
}
379380
private void OnConvertModeChanged(object sender, SelectionChangedEventArgs e) {
380381
if (!loaded)
@@ -471,7 +472,7 @@ private void OnBackup(object sender, RoutedEventArgs e) {
471472
Thread thread = new Thread(() => {
472473
Processing.BackupFiles(input, output);
473474
});
474-
Processing.StartProgressThread(this, "Backing Up...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, thread);
475+
Processing.StartProgressThread(this, "Backing Up...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, Config.PremultiplyAlpha, thread);
475476
}
476477
private void OnRestore(object sender, RoutedEventArgs e) {
477478
string input = Config.Backup.FolderBackup;
@@ -495,7 +496,7 @@ private void OnRestore(object sender, RoutedEventArgs e) {
495496
Thread thread = new Thread(() => {
496497
Processing.RestoreFiles(input, output);
497498
});
498-
Processing.StartProgressThread(this, "Restoring...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, thread);
499+
Processing.StartProgressThread(this, "Restoring...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, Config.PremultiplyAlpha, thread);
499500
}
500501
private void OnBackupChangeContent(object sender, RoutedEventArgs e) {
501502
System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
@@ -556,7 +557,7 @@ private void OnRunScript(object sender, RoutedEventArgs e) {
556557
thread = new Thread(() => {
557558
Processing.RunScript(input);
558559
});
559-
Processing.StartProgressThread(this, "Running Script...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, thread);
560+
Processing.StartProgressThread(this, "Running Script...", Config.AutoCloseProgress, Config.CompressImages, Config.CompletionSound, Config.PremultiplyAlpha, thread);
560561
}
561562
private void OnChangeScript(object sender, RoutedEventArgs e) {
562563
OpenFileDialog dialog = new OpenFileDialog();
@@ -648,7 +649,7 @@ private void OnFileDrop(object sender, DragEventArgs e) {
648649
Thread thread = new Thread(() => {
649650
Processing.ProcessDropFiles(extractFiles.ToArray(), convertFiles.ToArray(), scriptFiles.ToArray());
650651
});
651-
Processing.StartProgressThread(this, "Processing Drop Files...", Config.AutoCloseDropProgress, Config.CompressImages, Config.CompletionSound, thread);
652+
Processing.StartProgressThread(this, "Processing Drop Files...", Config.AutoCloseDropProgress, Config.CompressImages, Config.CompletionSound, Config.PremultiplyAlpha, thread);
652653
}
653654
}
654655
}
@@ -730,6 +731,11 @@ private void OnExit(object sender, RoutedEventArgs e) {
730731
Close();
731732
}
732733

734+
private void OnPremultiplyAlphaChecked(object sender, RoutedEventArgs e) {
735+
if (!loaded)
736+
return;
737+
Config.PremultiplyAlpha = menuItemPremultiply.IsChecked;
738+
}
733739
private void OnCompressImagesChecked(object sender, RoutedEventArgs e) {
734740
if (!loaded)
735741
return;

0 commit comments

Comments
 (0)