diff --git a/TelltaleTextureTool/TelltaleTextureTool/Converter.cs b/TelltaleTextureTool/TelltaleTextureTool/Converter.cs
index fa776de..ea17ab9 100644
--- a/TelltaleTextureTool/TelltaleTextureTool/Converter.cs
+++ b/TelltaleTextureTool/TelltaleTextureTool/Converter.cs
@@ -175,7 +175,7 @@ public static void ConvertTextureFromD3DtxToOthers(string sourceFilePath, string
Texture texture = new(array, TextureType.D3DTX);
- texture.ChangePreviewImage(options, true);
+ texture.TransformTexture(options, true, false);
texture.SaveTexture(Path.Combine(destinationDirectory, Path.GetFileNameWithoutExtension(sourceFilePath)), newTextureType);
texture.Release();
@@ -249,7 +249,7 @@ public static void ConvertTextureFromOthersToD3Dtx(string sourceFilePath, string
options.IsSRGB = true;
}
- texture.ChangePreviewImage(options, true);
+ texture.TransformTexture(options, true, false);
// Get the image
texture.GetDDSInformation(out D3DTXMetadata metadata, out ImageSection[] sections, flags);
@@ -259,8 +259,6 @@ public static void ConvertTextureFromOthersToD3Dtx(string sourceFilePath, string
metadata.Platform = options.PlatformType;
}
- Console.WriteLine("DXGI: " + texture.Metadata.Format);
- Console.WriteLine(metadata.Format);
// Modify the d3dtx file using our dds data
d3dtxMaster.ModifyD3DTX(metadata, sections);
diff --git a/TelltaleTextureTool/TelltaleTextureTool/GUI/Image/ImageData.cs b/TelltaleTextureTool/TelltaleTextureTool/GUI/Image/ImageData.cs
index 920ef8e..e8b0966 100644
--- a/TelltaleTextureTool/TelltaleTextureTool/GUI/Image/ImageData.cs
+++ b/TelltaleTextureTool/TelltaleTextureTool/GUI/Image/ImageData.cs
@@ -8,6 +8,8 @@
using System.Runtime.InteropServices;
using TelltaleTextureTool.TelltaleEnums;
using TelltaleTextureTool.Graphics;
+using Avalonia;
+using Avalonia.Platform;
namespace TelltaleTextureTool;
@@ -15,15 +17,13 @@ public class ImageData
{
public ImageProperties ImageProperties { get; set; } = new ImageProperties();
public Texture DDSImage { get; set; } = new Texture();
-
+ public TextureType CurrentTextureType { get; set; }
public uint MaxMip { get; set; }
public uint MaxFace { get; set; }
private string CurrentFilePath { get; set; } = string.Empty;
private bool IsSamePath { get; set; }
private bool HasPixelData { get; set; }
- private TextureType CurrentTextureType { get; set; }
-
private TelltaleToolGame Game { get; set; }
private bool IsLegacyConsole { get; set; }
@@ -70,7 +70,7 @@ public void ApplyEffects(ImageAdvancedOptions options)
{
try
{
- DDSImage.ChangePreviewImage(options);
+ DDSImage.TransformTexture(options, false, true);
DDSImage.GetBounds(out uint maxMip, out uint maxFace);
MaxMip = maxMip;
@@ -188,11 +188,11 @@ private void GetImageDataFromCommon(out ImageProperties imageProperties)
///
///
/// The bitmap from the mip and face.
- public Bitmap GetBitmapFromScratchImage(uint mip = 0, uint face = 0)
+ public WriteableBitmap GetBitmapFromScratchImage(uint mip = 0, uint face = 0)
{
if (TextureType.Unknown == CurrentTextureType)
{
- return new Bitmap(MemoryStream.Null);
+ return null;
}
DDSImage.GetBounds(out uint maxMip, out uint maxFace);
@@ -210,26 +210,24 @@ public Bitmap GetBitmapFromScratchImage(uint mip = 0, uint face = 0)
DDSImage.GetData(mip, face, out ulong width, out ulong height, out ulong pitch, out ulong length, out byte[] pixelData);
- // Converts the data into writeableBitmap. (TODO Insert a link to the code)
- var imageInfo = new SKImageInfo((int)width, (int)height, SKColorType.Rgba8888);
- var handle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
- var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(pixelData, 0);
- using var data = SKData.Create(ptr, (int)length, (_, _) => handle.Free());
- using var skImage = SKImage.FromPixels(imageInfo, data, (int)pitch);
- using var bitmap = SKBitmap.FromImage(skImage);
-
- // Create a memory stream to hold the PNG data
- var memoryStream = new MemoryStream();
+ // Create a WriteableBitmap in RGBA8888 format
+ var bitmap = new WriteableBitmap(
+ new PixelSize((int)width, (int)height),
+ new Vector(96, 96), // Set DPI as necessary
+ PixelFormat.Rgba8888,
+ AlphaFormat.Unpremul);
- // Encode the bitmap to PNG and write it to the memory stream
- var wstream = new SKManagedWStream(memoryStream);
-
- var success = bitmap.Encode(wstream, SKEncodedImageFormat.Png, 95);
- Console.WriteLine(success ? "Image converted successfully" : "Image conversion failed");
+ // Lock the WriteableBitmap's back buffer to write pixel data
+ using (var framebuffer = bitmap.Lock())
+ {
+ IntPtr framebufferPtr = framebuffer.Address;
+ int framebufferRowBytes = framebuffer.RowBytes;
- memoryStream.Position = 0;
+ // Copy pixelData to the WriteableBitmap's memory
+ Marshal.Copy(pixelData, 0, framebufferPtr, (int)length);
+ }
- return new Bitmap(memoryStream);
+ return bitmap;
}
private static void GetImageDataFromInvalid(out ImageProperties imageProperties)
diff --git a/TelltaleTextureTool/TelltaleTextureTool/GUI/ViewModels/MainViewModel.cs b/TelltaleTextureTool/TelltaleTextureTool/GUI/ViewModels/MainViewModel.cs
index a3daf4f..78d1abc 100644
--- a/TelltaleTextureTool/TelltaleTextureTool/GUI/ViewModels/MainViewModel.cs
+++ b/TelltaleTextureTool/TelltaleTextureTool/GUI/ViewModels/MainViewModel.cs
@@ -33,7 +33,7 @@ public class EnumDisplayNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- if (value == null)
+ if (value is null)
return string.Empty;
// Get the field in the enum type that matches the current enum value
@@ -395,7 +395,7 @@ public async Task DeleteFileButton_Click()
var result = await MessageBoxManager.GetMessageBoxStandard(messageBox)
.ShowWindowDialogAsync(mainWindow);
- if (result != ButtonResult.Yes) return;
+ if (result is not ButtonResult.Yes) return;
Directory.Delete(textureFilePath);
}
@@ -489,7 +489,7 @@ public async Task ContextMenuOpenFileCommand()
{
try
{
- if (DataGridSelectedItem == null)
+ if (DataGridSelectedItem is null)
return;
var workingDirectoryFile =
@@ -514,7 +514,7 @@ public async Task ContextMenuOpenFolderCommand()
try
{
// if there is no valid item selected, don't continue
- if (DataGridSelectedItem == null)
+ if (DataGridSelectedItem is null)
return;
// get our selected file object from the working directory
@@ -540,9 +540,9 @@ public async Task ContextMenuOpenFileExplorerCommand()
{
try
{
- if (DirectoryPath == null) return;
+ if (DirectoryPath is null) return;
- if (DataGridSelectedItem == null)
+ if (DataGridSelectedItem is null)
{
if (Directory.Exists(DirectoryPath))
await OpenFileExplorer(DirectoryPath);
@@ -564,7 +564,7 @@ public async Task ContextMenuOpenFileExplorerCommand()
[RelayCommand]
public async Task RefreshDirectoryButton_Click()
{
- if (DirectoryPath != null && DirectoryPath != string.Empty)
+ if (DirectoryPath is not null && DirectoryPath != string.Empty)
{
await RefreshUiAsync();
}
@@ -601,7 +601,7 @@ public async Task ConvertButton_Click()
{
try
{
- if (DataGridSelectedItem == null) return;
+ if (DataGridSelectedItem is null) return;
var workingDirectoryFile =
DataGridSelectedItem;
@@ -624,7 +624,7 @@ public async Task ConvertButton_Click()
AllowMultiple = false,
});
- if (folderPath is null || folderPath.Count == 0)
+ if (folderPath is null || folderPath.Count is 0)
{
return;
}
@@ -697,7 +697,7 @@ public async Task DebugButton_Click()
{
try
{
- if (DataGridSelectedItem == null) return;
+ if (DataGridSelectedItem is null) return;
var workingDirectoryFile =
DataGridSelectedItem;
@@ -706,7 +706,7 @@ public async Task DebugButton_Click()
string debugInfo = string.Empty;
- if (workingDirectoryFile.FileType == ".d3dtx")
+ if (workingDirectoryFile.FileType is ".d3dtx")
{
var d3dtx = new D3DTX_Master();
d3dtx.ReadD3DTXFile(textureFilePath, ImageAdvancedOptions.GameID, ImageAdvancedOptions.IsLegacyConsole);
@@ -777,7 +777,7 @@ public async Task ReturnDirectory_Click()
{
try
{
- if (Directory.GetParent(DirectoryPath) == null) return;
+ if (Directory.GetParent(DirectoryPath) is null) return;
WorkingDirectoryFiles.Clear();
await mainManager.SetWorkingDirectoryPath(Directory.GetParent(DirectoryPath).ToString());
DataGridSelectedItem = null;
@@ -828,7 +828,7 @@ private void ChangeComboBoxItemsByItemExtension(string itemExtension)
{string.Empty, _folderTypes}
};
- if (itemExtension == null)
+ if (itemExtension is null)
{
FromFormatsList = null;
ToFormatsList = null;
@@ -908,7 +908,7 @@ public async void RowDoubleTappedCommand(object? sender, TappedEventArgs args)
if (source is null) return;
if (source is Border)
{
- if (DataGridSelectedItem == null)
+ if (DataGridSelectedItem is null)
return;
var workingDirectoryFile =
@@ -946,7 +946,7 @@ public async void RowDoubleTappedCommand(object? sender, TappedEventArgs args)
private void UpdateUIElementsAsync()
{
- if (DataGridSelectedItem != null)
+ if (DataGridSelectedItem is not null)
{
var workingDirectoryFile = DataGridSelectedItem;
var path = workingDirectoryFile.FilePath;
@@ -960,7 +960,7 @@ private void UpdateUIElementsAsync()
throw new Exception("File or directory do not exist anymore! Refreshing the directory.");
}
- DebugButtonStatus = extension == ".d3dtx" || extension == ".dds";
+ DebugButtonStatus = extension is ".d3dtx" || extension is ".dds";
SaveButtonStatus = File.Exists(path);
DeleteButtonStatus = true;
ContextOpenFolderStatus = Directory.Exists(path);
@@ -1029,7 +1029,7 @@ public async Task PreviewImage()
{
UpdateUIElementsAsync();
- if (DataGridSelectedItem == null)
+ if (DataGridSelectedItem is null)
return;
var workingDirectoryFile = DataGridSelectedItem;
@@ -1049,9 +1049,14 @@ public async Task PreviewImage()
ImageData.Initialize(filePath, textureType, ImageAdvancedOptions.GameID, ImageAdvancedOptions.IsLegacyConsole);
+ if (textureType is TextureType.Unknown)
+ {
+ ImageData.Reset();
+ }
+
ImageAdvancedOptions = ImageData.GetImageAdvancedOptions(ImageAdvancedOptions);
- if (textureType != TextureType.Unknown)
+ if (textureType is not TextureType.Unknown)
{
ImageData.ApplyEffects(ImageAdvancedOptions);
}
@@ -1068,7 +1073,7 @@ public async Task PreviewImage()
ImageProperties = ImageData.ImageProperties;
- if (textureType != TextureType.Unknown)
+ if (textureType is not TextureType.Unknown)
{
ImagePreview = ImageData.GetBitmapFromScratchImage(MipValue, FaceValue);
}
@@ -1092,7 +1097,7 @@ public async Task UpdateBitmap()
{
try
{
- if (DataGridSelectedItem == null)
+ if (DataGridSelectedItem is null)
return;
var workingDirectoryFile = DataGridSelectedItem;
@@ -1103,7 +1108,7 @@ public async Task UpdateBitmap()
if (extension != string.Empty)
textureType = GetTextureTypeFromItem(extension.ToUpperInvariant().Remove(0, 1));
- if (textureType == TextureType.Unknown)
+ if (textureType is TextureType.Unknown)
{
return;
}
@@ -1118,7 +1123,10 @@ public async Task UpdateBitmap()
ImageProperties = ImageData.ImageProperties;
- ImagePreview = ImageData.GetBitmapFromScratchImage(MipValue, FaceValue);
+ if (textureType is not TextureType.Unknown)
+ {
+ ImagePreview = ImageData.GetBitmapFromScratchImage(MipValue, FaceValue);
+ }
}
catch (Exception ex)
{
@@ -1130,11 +1138,13 @@ public async Task UpdateBitmap()
protected override async void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
- if (e.PropertyName == nameof(MipValue) || e.PropertyName == nameof(FaceValue))
+ if (e.PropertyName is nameof(MipValue) || e.PropertyName is nameof(FaceValue))
{
- ImagePreview = ImageData.GetBitmapFromScratchImage(MipValue, FaceValue);
+ if (ImageData.CurrentTextureType is not TextureType.Unknown)
+ ImagePreview = ImageData.GetBitmapFromScratchImage(MipValue, FaceValue);
+ else { ImagePreview = new SvgImage { Source = SvgSource.Load(ErrorSvgFilename, _assetsUri) }; }
}
- if (e.PropertyName == nameof(ImageAdvancedOptions))
+ if (e.PropertyName is nameof(ImageAdvancedOptions))
{
await UpdateBitmap();
}
diff --git a/TelltaleTextureTool/TelltaleTextureTool/Graphics/TextureManager.cs b/TelltaleTextureTool/TelltaleTextureTool/Graphics/TextureManager.cs
index 53cf3b8..b59e2a7 100644
--- a/TelltaleTextureTool/TelltaleTextureTool/Graphics/TextureManager.cs
+++ b/TelltaleTextureTool/TelltaleTextureTool/Graphics/TextureManager.cs
@@ -88,7 +88,7 @@ public static string GetTextureDebugInfo(string filePath, TextureType textureTyp
Console.WriteLine(e.Message);
scratchImage.Release();
throw new Exception("Failed to load image!");
- }
+ }
string debugInfo = GetTextureDebugInfo(scratchImage.GetMetadata());
@@ -392,16 +392,14 @@ unsafe public static void DefaultCopy(Vector4* outPixels, Vector4* inPixels, ulo
///
public unsafe partial class Texture
{
- public string FilePath { get; set; } = string.Empty;
- private ScratchImage Image { get; set; }
public TexMetadata Metadata { get; set; }
-
- private ScratchImage OriginalImage { get; set; }
- private TexMetadata OriginalMetadata { get; set; }
-
public ImageAdvancedOptions CurrentOptions { get; set; } = new ImageAdvancedOptions();
public TextureType TextureType { get; set; } = TextureType.Unknown;
+
+ private ScratchImage Image { get; set; }
+ private ScratchImage OriginalImage { get; set; }
private DXGIFormat PreviewFormat { get; set; }
+ private string FilePath { get; set; } = string.Empty;
private ulong PreviewWidth { get; set; }
private ulong PreviewHeight { get; set; }
private uint PreviewMip { get; set; } = 0;
@@ -440,7 +438,6 @@ private void InitializeSingleScratchImage(byte[] ddsData, bool isCopy, DDSFlags
Blob blob = DirectXTex.CreateBlob();
TexMetadata meta = new();
- Console.WriteLine("DDS LENGTH: " + ddsData.Length);
fixed (byte* srcPtr = src)
{
DirectXTex.LoadFromDDSMemory(srcPtr, (nuint)src.Length, flags, ref meta, ref Image).ThrowIf();
@@ -454,7 +451,6 @@ private void InitializeSingleScratchImage(byte[] ddsData, bool isCopy, DDSFlags
else
{
OriginalImage = Image;
- OriginalMetadata = meta;
}
blob.Release();
@@ -479,35 +475,8 @@ public string GetDDSDebugInfo()
return GetTextureDebugInfo(Metadata);
}
- public void ConvertToRGBA()
- {
- ScratchImage destImage = DirectXTex.CreateScratchImage();
-
- TexMetadata ogMeta = Image.GetMetadata();
- Decompress(DXGIFormat.R8G8B8A8_UNORM);
-
- if (Image.GetMetadata().Format != (uint)DXGIFormat.R8G8B8A8_UNORM)
- {
- DirectXTex.Convert2(Image.GetImages(), Image.GetImageCount(), ref ogMeta, (int)DXGIFormat.R8G8B8A8_UNORM, TexFilterFlags.Default, 0.5f, ref destImage).ThrowIf();
-
- Image.Release();
- Image = destImage;
- }
- else
- {
- destImage.Release();
- }
-
- Metadata = Image.GetMetadata();
- }
-
public byte[] GetSectionPixelData(uint mip, uint face)
{
- if ((uint)Image.GetMetadata().Format != (uint)DXGIFormat.R8G8B8A8_UNORM)
- {
- ConvertToRGBA();
- }
-
uint slice = 0;
// Swap slice and face if it's a 3D texture, because they don't have faces.
@@ -519,14 +488,46 @@ public byte[] GetSectionPixelData(uint mip, uint face)
var image = DirectXTex.GetImage(Image, (ulong)mip, (ulong)face, (ulong)slice);
- PreviewFormat = (DXGIFormat)image->Format;
- PreviewWidth = image->Width;
- PreviewHeight = image->Height;
- PreviewMip = mip;
+ ScratchImage destImage = DirectXTex.CreateScratchImage();
+ byte[] pixels;
+
+ try
+ {
+ DirectXTex.InitializeFromImage(destImage, *image, false, CPFlags.None);
+
+ if (DirectXTex.IsCompressed(destImage.GetMetadata().Format))
+ {
+ ScratchImage newDestImage = DirectXTex.CreateScratchImage();
+
+ DirectXTex.Decompress(destImage.GetImage(0, 0, 0), (int)DXGIFormat.R8G8B8A8_UNORM, ref newDestImage).ThrowIf();
+
+ destImage.Release();
+ destImage = newDestImage;
+ }
+
+ if (destImage.GetMetadata().Format != (uint)DXGIFormat.R8G8B8A8_UNORM)
+ {
+ ScratchImage newDestImage = DirectXTex.CreateScratchImage();
+
+ DirectXTex.Convert(destImage.GetImage(0, 0, 0), (int)DXGIFormat.R8G8B8A8_UNORM, TexFilterFlags.Default, 0.5f, ref newDestImage).ThrowIf();
- byte[] pixels = new byte[image->SlicePitch];
+ destImage.Release();
+ destImage = newDestImage;
+ }
+
+ PreviewFormat = (DXGIFormat)destImage.GetMetadata().Format;
+ PreviewWidth = destImage.GetMetadata().Width;
+ PreviewHeight = destImage.GetMetadata().Height;
+ PreviewMip = mip;
- Marshal.Copy((nint)image->Pixels, pixels, 0, pixels.Length);
+ pixels = new byte[destImage.GetImage(0, 0, 0)->SlicePitch];
+
+ Marshal.Copy((nint)destImage.GetImage(0, 0, 0)->Pixels, pixels, 0, pixels.Length);
+ }
+ finally
+ {
+ destImage.Release();
+ }
return pixels;
}
@@ -635,8 +636,6 @@ public void TransformImage(ImageEffect conversionMode = ImageEffect.DEFAULT)
DirectXTex.TransformImage2(Image.GetImages(), Image.GetImageCount(), ref texMetadata, transformFunction, ref transformedImage).ThrowIf();
- Console.WriteLine("Transforming image" + Image.GetImageCount());
-
Image.Release();
Image = transformedImage;
@@ -693,7 +692,6 @@ private void Initialize(string filePath, TextureType textureType, bool isCopy =
OriginalImage.Release();
}
OriginalImage = scratchImage;
- OriginalMetadata = texMetadata;
}
}
@@ -707,8 +705,6 @@ private void Initialize(string filePath, TextureType textureType, bool isCopy =
private void ResetImageToOriginal()
{
- Metadata = OriginalMetadata;
-
if (TextureType != TextureType.D3DTX)
{
Initialize(FilePath, TextureType, true, DDSFlags.None);
@@ -720,7 +716,13 @@ private void ResetImageToOriginal()
}
}
- public void ChangePreviewImage(ImageAdvancedOptions options, bool keepOriginal = false)
+ ///
+ /// Changes the image itself based on the options provided.
+ ///
+ ///
+ ///
+ ///
+ public void TransformTexture(ImageAdvancedOptions options, bool keepOriginal = false, bool convertingOnly = false)
{
ResetImageToOriginal();
@@ -801,6 +803,7 @@ public void ChangePreviewImage(ImageAdvancedOptions options, bool keepOriginal =
Compress((DXGIFormat)OriginalImage.GetMetadata().Format);
}
+
if (options.EnableSwizzle && options.IsSwizzle)
{
Swizzle(options.PlatformType);