Skip to content

Commit 556ae6e

Browse files
Ka1serM4sval
andauthored
Texture Changes & HDR Preview/Export (#559)
* texture refactor * fix bgra in opengl Co-authored-by: Asval <asval.contactme@gmail.com>
1 parent edebff0 commit 556ae6e

File tree

9 files changed

+101
-29
lines changed

9 files changed

+101
-29
lines changed

CUE4Parse

Submodule CUE4Parse updated 90 files

FModel/Creator/Bases/FN/BaseIcon.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ protected void GetSeries(UObject uObject)
159159
{
160160
if (uObject is UTexture2D texture2D)
161161
{
162-
SeriesBackground = texture2D.Decode();
162+
SeriesBackground = texture2D.Decode().ToSkBitmap();
163163
return;
164164
}
165165

FModel/Creator/Utils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public static SKBitmap GetBitmap(UMaterialInstanceConstant material)
130130
public static SKBitmap GetB64Bitmap(string b64) => SKBitmap.Decode(new MemoryStream(Convert.FromBase64String(b64)) { Position = 0 });
131131
public static SKBitmap GetBitmap(FSoftObjectPath softObjectPath) => GetBitmap(softObjectPath.Load<UTexture2D>());
132132
public static SKBitmap GetBitmap(string fullPath) => TryLoadObject(fullPath, out UTexture2D texture) ? GetBitmap(texture) : null;
133-
public static SKBitmap GetBitmap(UTexture2D texture) => texture.Decode(UserSettings.Default.CurrentDir.TexturePlatform);
133+
public static SKBitmap GetBitmap(UTexture2D texture) => texture.Decode(UserSettings.Default.CurrentDir.TexturePlatform).ToSkBitmap();
134134
public static SKBitmap GetBitmap(byte[] data) => SKBitmap.Decode(data);
135135

136136
public static SKBitmap ResizeWithRatio(this SKBitmap me, double width, double height)

FModel/MainWindow.xaml.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ private async void OnLoaded(object sender, RoutedEventArgs e)
6363

6464
await ApplicationViewModel.InitOodle();
6565
await ApplicationViewModel.InitZlib();
66+
await ApplicationViewModel.InitDetex();
6667
await _applicationView.CUE4Parse.Initialize();
6768
await _applicationView.AesManager.InitAes();
6869
await _applicationView.UpdateProvider(true);

FModel/ViewModels/ApplicationViewModel.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Linq;
77
using System.Threading.Tasks;
88
using System.Windows;
9+
using CUE4Parse_Conversion.Textures.BC;
910
using CUE4Parse.Compression;
1011
using CUE4Parse.Encryption.Aes;
1112
using CUE4Parse.UE4.Objects.Core.Misc;
@@ -258,4 +259,19 @@ public static async ValueTask InitZlib()
258259

259260
ZlibHelper.Initialize(zlibPath);
260261
}
262+
263+
public static async ValueTask InitDetex()
264+
{
265+
var detexPath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", DetexHelper.DLL_NAME);
266+
if (File.Exists(DetexHelper.DLL_NAME))
267+
{
268+
File.Move(DetexHelper.DLL_NAME, detexPath, true);
269+
}
270+
else if (!File.Exists(detexPath))
271+
{
272+
await DetexHelper.LoadDllAsync(detexPath);
273+
}
274+
275+
DetexHelper.Initialize(detexPath);
276+
}
261277
}

FModel/ViewModels/TabControlViewModel.cs

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ namespace FModel.ViewModels;
2222

2323
public class TabImage : ViewModel
2424
{
25-
public string ExportName { get; }
25+
public string ExportName { get; set; }
26+
2627
public byte[] ImageBuffer { get; set; }
2728

2829
public TabImage(string name, bool rnn, SKBitmap img)
@@ -32,6 +33,13 @@ public TabImage(string name, bool rnn, SKBitmap img)
3233
SetImage(img);
3334
}
3435

36+
public TabImage(string name, bool rnn, CTexture img)
37+
{
38+
ExportName = name;
39+
RenderNearestNeighbor = rnn;
40+
SetImage(img);
41+
}
42+
3543
private BitmapImage _image;
3644
public BitmapImage Image
3745
{
@@ -71,11 +79,42 @@ private void SetImage(SKBitmap bitmap)
7179
}
7280

7381
_bmp = bitmap;
74-
using var data = _bmp.Encode(NoAlpha ? ETextureFormat.Jpeg : UserSettings.Default.TextureExportFormat, 100);
82+
ExportName += "." + (NoAlpha ? "jpg" : "png");
83+
using var data = _bmp.Encode(NoAlpha ? SKEncodedImageFormat.Jpeg : SKEncodedImageFormat.Png, 100);
7584
using var stream = new MemoryStream(ImageBuffer = data.ToArray(), false);
76-
if (UserSettings.Default.TextureExportFormat == ETextureFormat.Tga)
85+
var image = new BitmapImage();
86+
image.BeginInit();
87+
image.CacheOption = BitmapCacheOption.OnLoad;
88+
image.StreamSource = stream;
89+
image.EndInit();
90+
image.Freeze();
91+
Image = image;
92+
}
93+
94+
private void SetImage(CTexture bitmap)
95+
{
96+
if (bitmap is null)
97+
{
98+
ImageBuffer = null;
99+
Image = null;
77100
return;
101+
}
102+
103+
_bmp = bitmap.ToSkBitmap();
104+
byte[] imageData = _bmp.Encode(NoAlpha ? SKEncodedImageFormat.Jpeg : SKEncodedImageFormat.Png, 100).ToArray();
78105

106+
if (PixelFormatUtils.IsHDR(bitmap.PixelFormat) || (UserSettings.Default.TextureExportFormat != ETextureFormat.Jpeg && UserSettings.Default.TextureExportFormat != ETextureFormat.Png))
107+
{
108+
ImageBuffer = bitmap.Encode(UserSettings.Default.TextureExportFormat, out var ext);
109+
ExportName += "." + ext;
110+
}
111+
else
112+
{
113+
ImageBuffer = imageData;
114+
ExportName += "." + (NoAlpha ? "jpg" : "png");
115+
}
116+
117+
using var stream = new MemoryStream(imageData);
79118
var image = new BitmapImage();
80119
image.BeginInit();
81120
image.CacheOption = BitmapCacheOption.OnLoad;
@@ -253,7 +292,7 @@ public void SoftReset(GameFile entry)
253292
public void AddImage(UTexture texture, bool save, bool updateUi)
254293
{
255294
var appendLayerNumber = false;
256-
var img = new SKBitmap[1];
295+
var img = new CTexture[1];
257296
if (texture is UTexture2DArray textureArray)
258297
{
259298
img = textureArray.DecodeTextureArray(UserSettings.Default.CurrentDir.TexturePlatform);
@@ -264,7 +303,7 @@ public void AddImage(UTexture texture, bool save, bool updateUi)
264303
img[0] = texture.Decode(UserSettings.Default.CurrentDir.TexturePlatform);
265304
if (texture is UTextureCube)
266305
{
267-
img[0] = img[0]?.ToPanorama();
306+
img[0] = img[0].ToPanorama();
268307
}
269308
}
270309

@@ -279,6 +318,29 @@ public void AddImage(string name, bool rnn, SKBitmap[] img, bool save, bool upda
279318
}
280319
}
281320

321+
public void AddImage(string name, bool rnn, CTexture[] img, bool save, bool updateUi, bool appendLayerNumber = false)
322+
{
323+
for (var i = 0; i < img.Length; i++)
324+
{
325+
AddImage($"{name}{(appendLayerNumber ? $"_{i}" : "")}", rnn, img[i], save, updateUi);
326+
}
327+
}
328+
329+
public void AddImage(string name, bool rnn, CTexture img, bool save, bool updateUi)
330+
{
331+
Application.Current.Dispatcher.Invoke(() =>
332+
{
333+
var t = new TabImage(name, rnn, img);
334+
if (save) SaveImage(t, updateUi);
335+
if (!updateUi) return;
336+
337+
_images.Add(t);
338+
SelectedImage ??= t;
339+
RaisePropertyChanged("Page");
340+
RaisePropertyChanged("HasMultipleImages");
341+
});
342+
}
343+
282344
public void AddImage(string name, bool rnn, SKBitmap img, bool save, bool updateUi)
283345
{
284346
Application.Current.Dispatcher.Invoke(() =>
@@ -312,23 +374,14 @@ public void SetDocumentText(string text, bool save, bool updateUi)
312374
public void SaveImage() => SaveImage(SelectedImage, true);
313375
private void SaveImage(TabImage image, bool updateUi)
314376
{
315-
if (image == null) return;
316-
317-
var ext = UserSettings.Default.TextureExportFormat switch
318-
{
319-
ETextureFormat.Png => ".png",
320-
ETextureFormat.Jpeg => ".jpg",
321-
ETextureFormat.Tga => ".tga",
322-
_ => ".png"
323-
};
377+
if (image == null)
378+
return;
324379

325-
var fileName = image.ExportName + ext;
326-
var path = Path.Combine(UserSettings.Default.TextureDirectory,
327-
UserSettings.Default.KeepDirectoryStructure ? Entry.Directory : "", fileName!).Replace('\\', '/');
380+
var path = Path.Combine(UserSettings.Default.TextureDirectory, UserSettings.Default.KeepDirectoryStructure ? Entry.Directory : "", image.ExportName).Replace('\\', '/');
328381

329382
Directory.CreateDirectory(path.SubstringBeforeLast('/'));
330383

331-
SaveImage(image, path, fileName, updateUi);
384+
SaveImage(image, path, image.ExportName, updateUi);
332385
}
333386

334387
private void SaveImage(TabImage image, string path, string fileName, bool updateUi)

FModel/Views/Snooper/Options.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ public bool TryGetTexture(UTexture o, bool fix, out Texture texture)
193193
if (Textures.TryGetValue(guid, out texture)) return texture != null;
194194
if (o.Format == EPixelFormat.PF_BC6H) return false; // BC6H is not supported by Decode thus randomly crashes the app
195195

196-
SKBitmap bitmap = o switch
196+
var bitmap = o switch
197197
{
198198
UTexture2D texture2D => texture2D.Decode(UserSettings.Default.PreviewMaxTextureSize, UserSettings.Default.CurrentDir.TexturePlatform),
199199
UTexture2DArray texture2DArray => texture2DArray.DecodeTextureArray(UserSettings.Default.CurrentDir.TexturePlatform)?.FirstOrDefault(),
@@ -202,10 +202,9 @@ public bool TryGetTexture(UTexture o, bool fix, out Texture texture)
202202

203203
if (bitmap is not null)
204204
{
205-
texture = new Texture(bitmap, o);
205+
texture = new Texture(bitmap.ToSkBitmap(), o);
206206
if (fix) TextureHelper.FixChannels(_game, texture);
207207
Textures[guid] = texture;
208-
bitmap.Dispose();
209208
}
210209

211210
return texture != null;

FModel/Views/Snooper/Shading/Texture.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Numerics;
33
using System.Windows;
4+
using CUE4Parse_Conversion.Textures;
45
using CUE4Parse.UE4.Assets.Exports.Texture;
56
using CUE4Parse.UE4.Objects.Core.Math;
67
using CUE4Parse.UE4.Objects.Core.Misc;
@@ -90,15 +91,16 @@ public Texture(SKBitmap bitmap, UTexture texture2D) : this(TextureType.Normal)
9091
Height = bitmap.Height;
9192
Bind(TextureUnit.Texture0);
9293

93-
var internalFormat = Format switch
94+
var internalFormat = bitmap.ColorType switch
9495
{
95-
EPixelFormat.PF_G8 => PixelInternalFormat.R8,
96+
SKColorType.Gray8 => PixelInternalFormat.R8,
9697
_ => texture2D.SRGB ? PixelInternalFormat.Srgb : PixelInternalFormat.Rgb
9798
};
9899

99-
var pixelFormat = Format switch
100+
var pixelFormat = bitmap.ColorType switch
100101
{
101-
EPixelFormat.PF_G8 => PixelFormat.Red,
102+
SKColorType.Gray8 => PixelFormat.Red,
103+
SKColorType.Bgra8888 => PixelFormat.Bgra,
102104
_ => PixelFormat.Rgba
103105
};
104106

@@ -109,6 +111,7 @@ public Texture(SKBitmap bitmap, UTexture texture2D) : this(TextureType.Normal)
109111
GL.TexParameter(_target, TextureParameterName.TextureMaxLevel, 8);
110112

111113
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
114+
bitmap.Dispose();
112115
}
113116

114117
public Texture(FLinearColor color) : this(TextureType.Normal)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ FModel - An Unreal Engine Archives Explorer in C#
44
[![CI Status](https://img.shields.io/github/actions/workflow/status/4sval/FModel/qa.yml?label=CI)](https://github.com/4sval/FModel/actions)
55
[![Latest](https://img.shields.io/github/v/release/4sval/FModel?color=yellow)](https://fmodel.app/download)
66
[![Donate](https://img.shields.io/badge/sponsor-DB61A2?logo=GitHub-Sponsors&logoColor=white)](https://fmodel.app/donate)
7-
[![Discord](https://discordapp.com/api/guilds/637265123144237061/widget.png?style=shield)](https://fmodel.app/discord)
7+
[![Discord](https://discord.com/api/guilds/637265123144237061/widget.png?style=shield)](https://fmodel.app/discord)
88
***
99

1010
### Description:

0 commit comments

Comments
 (0)