mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 20:24:17 +01:00
Add Targa export.
This commit is contained in:
parent
c4853434c8
commit
ded910d8a1
5 changed files with 67 additions and 22 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 552246e595ffab2aaba2c75f578d564f8938fc9a
|
Subproject commit a38e9bcfb80c456102945bbb4c59f5621cae0442
|
||||||
|
|
@ -10,6 +10,7 @@ public class EditingApi(TextureManager textureManager) : IPenumbraApiEditing, IA
|
||||||
=> textureType switch
|
=> textureType switch
|
||||||
{
|
{
|
||||||
TextureType.Png => textureManager.SavePng(inputFile, outputFile),
|
TextureType.Png => textureManager.SavePng(inputFile, outputFile),
|
||||||
|
TextureType.Targa => textureManager.SaveTga(inputFile, outputFile),
|
||||||
TextureType.AsIsTex => textureManager.SaveAs(CombinedTexture.TextureSaveType.AsIs, mipMaps, true, inputFile, outputFile),
|
TextureType.AsIsTex => textureManager.SaveAs(CombinedTexture.TextureSaveType.AsIs, mipMaps, true, inputFile, outputFile),
|
||||||
TextureType.AsIsDds => textureManager.SaveAs(CombinedTexture.TextureSaveType.AsIs, mipMaps, false, inputFile, outputFile),
|
TextureType.AsIsDds => textureManager.SaveAs(CombinedTexture.TextureSaveType.AsIs, mipMaps, false, inputFile, outputFile),
|
||||||
TextureType.RgbaTex => textureManager.SaveAs(CombinedTexture.TextureSaveType.Bitmap, mipMaps, true, inputFile, outputFile),
|
TextureType.RgbaTex => textureManager.SaveAs(CombinedTexture.TextureSaveType.Bitmap, mipMaps, true, inputFile, outputFile),
|
||||||
|
|
@ -26,6 +27,7 @@ public class EditingApi(TextureManager textureManager) : IPenumbraApiEditing, IA
|
||||||
=> textureType switch
|
=> textureType switch
|
||||||
{
|
{
|
||||||
TextureType.Png => textureManager.SavePng(new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
TextureType.Png => textureManager.SavePng(new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
|
TextureType.Targa => textureManager.SaveTga(new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
TextureType.AsIsTex => textureManager.SaveAs(CombinedTexture.TextureSaveType.AsIs, mipMaps, true, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
TextureType.AsIsTex => textureManager.SaveAs(CombinedTexture.TextureSaveType.AsIs, mipMaps, true, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
TextureType.AsIsDds => textureManager.SaveAs(CombinedTexture.TextureSaveType.AsIs, mipMaps, false, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
TextureType.AsIsDds => textureManager.SaveAs(CombinedTexture.TextureSaveType.AsIs, mipMaps, false, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
TextureType.RgbaTex => textureManager.SaveAs(CombinedTexture.TextureSaveType.Bitmap, mipMaps, true, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
TextureType.RgbaTex => textureManager.SaveAs(CombinedTexture.TextureSaveType.Bitmap, mipMaps, true, new BaseImage(), outputFile, rgbaData, width, rgbaData.Length / 4 / width),
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,14 @@ public partial class CombinedTexture : IDisposable
|
||||||
SaveTask = textures.SavePng(_current.BaseImage, path, _current.RgbaPixels, _current.TextureWrap!.Width, _current.TextureWrap!.Height);
|
SaveTask = textures.SavePng(_current.BaseImage, path, _current.RgbaPixels, _current.TextureWrap!.Width, _current.TextureWrap!.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SaveAsTarga(TextureManager textures, string path)
|
||||||
|
{
|
||||||
|
if (!IsLoaded || _current == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SaveTask = textures.SaveTga(_current.BaseImage, path, _current.RgbaPixels, _current.TextureWrap!.Width, _current.TextureWrap!.Height);
|
||||||
|
}
|
||||||
|
|
||||||
private void SaveAs(TextureManager textures, string path, TextureSaveType type, bool mipMaps, bool writeTex)
|
private void SaveAs(TextureManager textures, string path, TextureSaveType type, bool mipMaps, bool writeTex)
|
||||||
{
|
{
|
||||||
if (!IsLoaded || _current == null)
|
if (!IsLoaded || _current == null)
|
||||||
|
|
@ -72,6 +80,7 @@ public partial class CombinedTexture : IDisposable
|
||||||
".tex" => TextureType.Tex,
|
".tex" => TextureType.Tex,
|
||||||
".dds" => TextureType.Dds,
|
".dds" => TextureType.Dds,
|
||||||
".png" => TextureType.Png,
|
".png" => TextureType.Png,
|
||||||
|
".tga" => TextureType.Targa,
|
||||||
_ => TextureType.Unknown,
|
_ => TextureType.Unknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -85,6 +94,9 @@ public partial class CombinedTexture : IDisposable
|
||||||
break;
|
break;
|
||||||
case TextureType.Png:
|
case TextureType.Png:
|
||||||
SaveAsPng(textures, path);
|
SaveAsPng(textures, path);
|
||||||
|
break;
|
||||||
|
case TextureType.Targa:
|
||||||
|
SaveAsTarga(textures, path);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException(
|
throw new ArgumentException(
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using OtterGui.Tasks;
|
||||||
using OtterTex;
|
using OtterTex;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.Formats.Png;
|
using SixLabors.ImageSharp.Formats.Png;
|
||||||
|
using SixLabors.ImageSharp.Formats.Tga;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
using Image = SixLabors.ImageSharp.Image;
|
using Image = SixLabors.ImageSharp.Image;
|
||||||
|
|
||||||
|
|
@ -33,10 +34,17 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SavePng(string input, string output)
|
public Task SavePng(string input, string output)
|
||||||
=> Enqueue(new SavePngAction(this, input, output));
|
=> Enqueue(new SaveImageSharpAction(this, input, output, TextureType.Png));
|
||||||
|
|
||||||
public Task SavePng(BaseImage image, string path, byte[]? rgba = null, int width = 0, int height = 0)
|
public Task SavePng(BaseImage image, string path, byte[]? rgba = null, int width = 0, int height = 0)
|
||||||
=> Enqueue(new SavePngAction(this, image, path, rgba, width, height));
|
=> Enqueue(new SaveImageSharpAction(this, image, path, TextureType.Png, rgba, width, height));
|
||||||
|
|
||||||
|
public Task SaveTga(string input, string output)
|
||||||
|
=> Enqueue(new SaveImageSharpAction(this, input, output, TextureType.Targa));
|
||||||
|
|
||||||
|
public Task SaveTga(BaseImage image, string path, byte[]? rgba = null, int width = 0, int height = 0)
|
||||||
|
=> Enqueue(new SaveImageSharpAction(this, image, path, TextureType.Targa, rgba, width, height));
|
||||||
|
|
||||||
|
|
||||||
public Task SaveAs(CombinedTexture.TextureSaveType type, bool mipMaps, bool asTex, string input, string output)
|
public Task SaveAs(CombinedTexture.TextureSaveType type, bool mipMaps, bool asTex, string input, string output)
|
||||||
=> Enqueue(new SaveAsAction(this, type, mipMaps, asTex, input, output));
|
=> Enqueue(new SaveAsAction(this, type, mipMaps, asTex, input, output));
|
||||||
|
|
@ -66,44 +74,65 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SavePngAction : IAction
|
private class SaveImageSharpAction : IAction
|
||||||
{
|
{
|
||||||
private readonly TextureManager _textures;
|
private readonly TextureManager _textures;
|
||||||
private readonly string _outputPath;
|
private readonly string _outputPath;
|
||||||
private readonly ImageInputData _input;
|
private readonly ImageInputData _input;
|
||||||
|
private readonly TextureType _type;
|
||||||
|
|
||||||
public SavePngAction(TextureManager textures, string input, string output)
|
public SaveImageSharpAction(TextureManager textures, string input, string output, TextureType type)
|
||||||
{
|
{
|
||||||
_textures = textures;
|
_textures = textures;
|
||||||
_input = new ImageInputData(input);
|
_input = new ImageInputData(input);
|
||||||
_outputPath = output;
|
_outputPath = output;
|
||||||
|
_type = type;
|
||||||
|
if (_type.ReduceToBehaviour() is not TextureType.Png)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(type), type, $"Can not save as {type} with ImageSharp.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavePngAction(TextureManager textures, BaseImage image, string path, byte[]? rgba = null, int width = 0, int height = 0)
|
public SaveImageSharpAction(TextureManager textures, BaseImage image, string path, TextureType type, byte[]? rgba = null, int width = 0,
|
||||||
|
int height = 0)
|
||||||
{
|
{
|
||||||
_textures = textures;
|
_textures = textures;
|
||||||
_input = new ImageInputData(image, rgba, width, height);
|
_input = new ImageInputData(image, rgba, width, height);
|
||||||
_outputPath = path;
|
_outputPath = path;
|
||||||
|
_type = type;
|
||||||
|
if (_type.ReduceToBehaviour() is not TextureType.Png)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(type), type, $"Can not save as {type} with ImageSharp.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Execute(CancellationToken cancel)
|
public void Execute(CancellationToken cancel)
|
||||||
{
|
{
|
||||||
_textures._logger.Information($"[{nameof(TextureManager)}] Saving {_input} as .png to {_outputPath}...");
|
_textures._logger.Information($"[{nameof(TextureManager)}] Saving {_input} as {_type} to {_outputPath}...");
|
||||||
var (image, rgba, width, height) = _input.GetData(_textures);
|
var (image, rgba, width, height) = _input.GetData(_textures);
|
||||||
cancel.ThrowIfCancellationRequested();
|
cancel.ThrowIfCancellationRequested();
|
||||||
Image<Rgba32>? png = null;
|
Image<Rgba32>? data = null;
|
||||||
if (image.Type is TextureType.Unknown)
|
if (image.Type is TextureType.Unknown)
|
||||||
{
|
{
|
||||||
if (rgba != null && width > 0 && height > 0)
|
if (rgba != null && width > 0 && height > 0)
|
||||||
png = ConvertToPng(rgba, width, height).AsPng!;
|
data = ConvertToPng(rgba, width, height).AsPng!;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
png = ConvertToPng(image, cancel, rgba).AsPng!;
|
data = ConvertToPng(image, cancel, rgba).AsPng!;
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel.ThrowIfCancellationRequested();
|
cancel.ThrowIfCancellationRequested();
|
||||||
png?.SaveAsync(_outputPath, new PngEncoder() { CompressionLevel = PngCompressionLevel.NoCompression }, cancel).Wait(cancel);
|
switch (_type)
|
||||||
|
{
|
||||||
|
case TextureType.Png:
|
||||||
|
data?.SaveAsync(_outputPath, new PngEncoder() { CompressionLevel = PngCompressionLevel.NoCompression }, cancel)
|
||||||
|
.Wait(cancel);
|
||||||
|
return;
|
||||||
|
case TextureType.Targa:
|
||||||
|
data?.SaveAsync(_outputPath, new TgaEncoder()
|
||||||
|
{
|
||||||
|
Compression = TgaCompression.None,
|
||||||
|
BitsPerPixel = TgaBitsPerPixel.Pixel32,
|
||||||
|
}, cancel).Wait(cancel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|
@ -111,7 +140,7 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
|
|
||||||
public bool Equals(IAction? other)
|
public bool Equals(IAction? other)
|
||||||
{
|
{
|
||||||
if (other is not SavePngAction rhs)
|
if (other is not SaveImageSharpAction rhs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return string.Equals(_outputPath, rhs._outputPath, StringComparison.OrdinalIgnoreCase) && _input.Equals(rhs._input);
|
return string.Equals(_outputPath, rhs._outputPath, StringComparison.OrdinalIgnoreCase) && _input.Equals(rhs._input);
|
||||||
|
|
@ -168,9 +197,8 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
var imageTypeBehaviour = image.Type.ReduceToBehaviour();
|
var imageTypeBehaviour = image.Type.ReduceToBehaviour();
|
||||||
var dds = _type switch
|
var dds = _type switch
|
||||||
{
|
{
|
||||||
CombinedTexture.TextureSaveType.AsIs when imageTypeBehaviour is TextureType.Png => ConvertToRgbaDds(image, _mipMaps,
|
CombinedTexture.TextureSaveType.AsIs when imageTypeBehaviour is TextureType.Png => ConvertToRgbaDds(image, _mipMaps, cancel,
|
||||||
cancel, rgba,
|
rgba, width, height),
|
||||||
width, height),
|
|
||||||
CombinedTexture.TextureSaveType.AsIs when imageTypeBehaviour is TextureType.Dds => AddMipMaps(image.AsDds!, _mipMaps),
|
CombinedTexture.TextureSaveType.AsIs when imageTypeBehaviour is TextureType.Dds => AddMipMaps(image.AsDds!, _mipMaps),
|
||||||
CombinedTexture.TextureSaveType.Bitmap => ConvertToRgbaDds(image, _mipMaps, cancel, rgba, width, height),
|
CombinedTexture.TextureSaveType.Bitmap => ConvertToRgbaDds(image, _mipMaps, cancel, rgba, width, height),
|
||||||
CombinedTexture.TextureSaveType.BC3 => ConvertToCompressedDds(image, _mipMaps, false, cancel, rgba, width, height),
|
CombinedTexture.TextureSaveType.BC3 => ConvertToCompressedDds(image, _mipMaps, false, cancel, rgba, width, height),
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
ImGuiUtil.SelectableHelpMarker(newDesc);
|
ImGuiUtil.SelectableHelpMarker(newDesc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RedrawOnSaveBox()
|
private void RedrawOnSaveBox()
|
||||||
{
|
{
|
||||||
|
|
@ -128,7 +128,8 @@ public partial class ModEditWindow
|
||||||
? "This saves the texture in place. This is not revertible."
|
? "This saves the texture in place. This is not revertible."
|
||||||
: $"This saves the texture in place. This is not revertible. Hold {_config.DeleteModModifier} to save.";
|
: $"This saves the texture in place. This is not revertible. Hold {_config.DeleteModModifier} to save.";
|
||||||
|
|
||||||
var buttonSize2 = new Vector2((ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X) / 2, 0);
|
var buttonSize2 = new Vector2((ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X) / 2, 0);
|
||||||
|
var buttonSize3 = new Vector2((ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X * 2) / 3, 0);
|
||||||
if (ImGuiUtil.DrawDisabledButton("Save in place", buttonSize2,
|
if (ImGuiUtil.DrawDisabledButton("Save in place", buttonSize2,
|
||||||
tt, !isActive || !canSaveInPlace || _center.IsLeftCopy && _currentSaveAs == (int)CombinedTexture.TextureSaveType.AsIs))
|
tt, !isActive || !canSaveInPlace || _center.IsLeftCopy && _currentSaveAs == (int)CombinedTexture.TextureSaveType.AsIs))
|
||||||
{
|
{
|
||||||
|
|
@ -141,17 +142,18 @@ public partial class ModEditWindow
|
||||||
if (ImGui.Button("Save as TEX", buttonSize2))
|
if (ImGui.Button("Save as TEX", buttonSize2))
|
||||||
OpenSaveAsDialog(".tex");
|
OpenSaveAsDialog(".tex");
|
||||||
|
|
||||||
if (ImGui.Button("Export as PNG", buttonSize2))
|
if (ImGui.Button("Export as TGA", buttonSize3))
|
||||||
|
OpenSaveAsDialog(".tga");
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (ImGui.Button("Export as PNG", buttonSize3))
|
||||||
OpenSaveAsDialog(".png");
|
OpenSaveAsDialog(".png");
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (ImGui.Button("Export as DDS", buttonSize2))
|
if (ImGui.Button("Export as DDS", buttonSize3))
|
||||||
OpenSaveAsDialog(".dds");
|
OpenSaveAsDialog(".dds");
|
||||||
|
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
|
|
||||||
var canConvertInPlace = canSaveInPlace && _left.Type is TextureType.Tex && _center.IsLeftCopy;
|
var canConvertInPlace = canSaveInPlace && _left.Type is TextureType.Tex && _center.IsLeftCopy;
|
||||||
|
|
||||||
var buttonSize3 = new Vector2((ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X * 2) / 3, 0);
|
|
||||||
if (ImGuiUtil.DrawDisabledButton("Convert to BC7", buttonSize3,
|
if (ImGuiUtil.DrawDisabledButton("Convert to BC7", buttonSize3,
|
||||||
"This converts the texture to BC7 format in place. This is not revertible.",
|
"This converts the texture to BC7 format in place. This is not revertible.",
|
||||||
!canConvertInPlace || _left.Format is DXGIFormat.BC7Typeless or DXGIFormat.BC7UNorm or DXGIFormat.BC7UNormSRGB))
|
!canConvertInPlace || _left.Format is DXGIFormat.BC7Typeless or DXGIFormat.BC7UNorm or DXGIFormat.BC7UNormSRGB))
|
||||||
|
|
@ -226,7 +228,8 @@ public partial class ModEditWindow
|
||||||
private void OpenSaveAsDialog(string defaultExtension)
|
private void OpenSaveAsDialog(string defaultExtension)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileNameWithoutExtension(_left.Path.Length > 0 ? _left.Path : _right.Path);
|
var fileName = Path.GetFileNameWithoutExtension(_left.Path.Length > 0 ? _left.Path : _right.Path);
|
||||||
_fileDialog.OpenSavePicker("Save Texture as TEX, DDS or PNG...", "Textures{.png,.dds,.tex},.tex,.dds,.png", fileName, defaultExtension,
|
_fileDialog.OpenSavePicker("Save Texture as TEX, DDS, PNG or TGA...", "Textures{.png,.dds,.tex,.tga},.tex,.dds,.png,.tga", fileName,
|
||||||
|
defaultExtension,
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
{
|
{
|
||||||
if (a)
|
if (a)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue