mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-25 05:40:21 -04:00
[GUI] Improve memory usage of image previews
- also a bit increased performance of alpha mask resizing for previews
This commit is contained in:
parent
01957a9443
commit
44a1240f5f
@ -797,7 +797,7 @@ namespace AssetStudioGUI
|
|||||||
var image = m_Texture2D.ConvertToImage(true);
|
var image = m_Texture2D.ConvertToImage(true);
|
||||||
if (image != null)
|
if (image != null)
|
||||||
{
|
{
|
||||||
var bitmap = new DirectBitmap(image.ConvertToBytes(), m_Texture2D.m_Width, m_Texture2D.m_Height);
|
var bitmap = new DirectBitmap(image);
|
||||||
image.Dispose();
|
image.Dispose();
|
||||||
assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
|
assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
|
||||||
switch (m_Texture2D.m_TextureSettings.m_FilterMode)
|
switch (m_Texture2D.m_TextureSettings.m_FilterMode)
|
||||||
@ -1215,10 +1215,10 @@ namespace AssetStudioGUI
|
|||||||
|
|
||||||
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
|
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
|
||||||
{
|
{
|
||||||
var image = m_Sprite.GetImage(spriteMaskVisibleMode);
|
var image = m_Sprite.GetImage(spriteMaskMode: spriteMaskVisibleMode);
|
||||||
if (image != null)
|
if (image != null)
|
||||||
{
|
{
|
||||||
var bitmap = new DirectBitmap(image.ConvertToBytes(), image.Width, image.Height);
|
var bitmap = new DirectBitmap(image);
|
||||||
image.Dispose();
|
image.Dispose();
|
||||||
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
|
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
|
||||||
PreviewTexture(bitmap);
|
PreviewTexture(bitmap);
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
using System;
|
using AssetStudio;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
@ -7,13 +10,16 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
public sealed class DirectBitmap : IDisposable
|
public sealed class DirectBitmap : IDisposable
|
||||||
{
|
{
|
||||||
public DirectBitmap(byte[] buff, int width, int height)
|
public DirectBitmap(Image<Bgra32> image)
|
||||||
{
|
{
|
||||||
Width = width;
|
Width = image.Width;
|
||||||
Height = height;
|
Height = image.Height;
|
||||||
|
var buff = BigArrayPool<byte>.Shared.Rent(Width * Height * 4);
|
||||||
|
image.CopyPixelDataTo(buff);
|
||||||
Bits = buff;
|
Bits = buff;
|
||||||
m_handle = GCHandle.Alloc(Bits, GCHandleType.Pinned);
|
m_handle = GCHandle.Alloc(Bits, GCHandleType.Pinned);
|
||||||
m_bitmap = new Bitmap(Width, Height, Stride, PixelFormat.Format32bppArgb, m_handle.AddrOfPinnedObject());
|
m_bitmap = new Bitmap(Width, Height, Stride, PixelFormat.Format32bppArgb, m_handle.AddrOfPinnedObject());
|
||||||
|
BigArrayPool<byte>.Shared.Return(buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
|
@ -231,10 +231,10 @@ namespace AssetStudioGUI
|
|||||||
public static bool ExportSprite(AssetItem item, string exportPath)
|
public static bool ExportSprite(AssetItem item, string exportPath)
|
||||||
{
|
{
|
||||||
var type = Properties.Settings.Default.convertType;
|
var type = Properties.Settings.Default.convertType;
|
||||||
var alphaMask = Properties.Settings.Default.exportSpriteWithMask ? SpriteMaskMode.On : SpriteMaskMode.Off;
|
var spriteMaskMode = Properties.Settings.Default.exportSpriteWithMask ? SpriteMaskMode.Export : SpriteMaskMode.Off;
|
||||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||||
return false;
|
return false;
|
||||||
var image = ((Sprite)item.Asset).GetImage(alphaMask);
|
var image = ((Sprite)item.Asset).GetImage(spriteMaskMode: spriteMaskMode);
|
||||||
if (image != null)
|
if (image != null)
|
||||||
{
|
{
|
||||||
using (image)
|
using (image)
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
using SixLabors.ImageSharp.Formats.Bmp;
|
using SixLabors.ImageSharp.Formats.Bmp;
|
||||||
using SixLabors.ImageSharp.Formats.Tga;
|
using SixLabors.ImageSharp.Formats.Tga;
|
||||||
using SixLabors.ImageSharp.Formats.Webp;
|
using SixLabors.ImageSharp.Formats.Webp;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
@ -51,16 +48,5 @@ namespace AssetStudio
|
|||||||
image.WriteToStream(stream, imageFormat);
|
image.WriteToStream(stream, imageFormat);
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] ConvertToBytes<TPixel>(this Image<TPixel> image) where TPixel : unmanaged, IPixel<TPixel>
|
|
||||||
{
|
|
||||||
using (image)
|
|
||||||
{
|
|
||||||
Span<byte> imageSpan = new byte[image.Width * image.Height * 4];
|
|
||||||
image.CopyPixelDataTo(imageSpan);
|
|
||||||
|
|
||||||
return MemoryMarshal.AsBytes(imageSpan).ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,13 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
Off,
|
Off,
|
||||||
On,
|
On,
|
||||||
MaskOnly
|
MaskOnly,
|
||||||
|
Export
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SpriteHelper
|
public static class SpriteHelper
|
||||||
{
|
{
|
||||||
public static Image<Bgra32> GetImage(this Sprite m_Sprite, SpriteMaskMode spriteMaskVisibleMode = SpriteMaskMode.On)
|
public static Image<Bgra32> GetImage(this Sprite m_Sprite, SpriteMaskMode spriteMaskMode = SpriteMaskMode.On)
|
||||||
{
|
{
|
||||||
if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))
|
if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))
|
||||||
{
|
{
|
||||||
@ -31,20 +32,19 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskVisibleMode != SpriteMaskMode.Off)
|
if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskMode != SpriteMaskMode.Off)
|
||||||
{
|
{
|
||||||
var tex = CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
|
var tex = CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
|
||||||
var alphaTex = CutImage(m_Sprite, m_AlphaTexture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
|
var alphaTex = CutImage(m_Sprite, m_AlphaTexture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
|
||||||
|
|
||||||
if (tex.Width != alphaTex.Width || tex.Height != alphaTex.Height)
|
switch (spriteMaskMode)
|
||||||
{
|
|
||||||
alphaTex.Mutate(x => x.Resize(tex.Width, tex.Height));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (spriteMaskVisibleMode)
|
|
||||||
{
|
{
|
||||||
case SpriteMaskMode.On:
|
case SpriteMaskMode.On:
|
||||||
return ApplyRGBMask(tex, alphaTex);
|
tex.ApplyRGBMask(alphaTex, isPreview: true);
|
||||||
|
return tex;
|
||||||
|
case SpriteMaskMode.Export:
|
||||||
|
tex.ApplyRGBMask(alphaTex);
|
||||||
|
return tex;
|
||||||
case SpriteMaskMode.MaskOnly:
|
case SpriteMaskMode.MaskOnly:
|
||||||
tex.Dispose();
|
tex.Dispose();
|
||||||
return alphaTex;
|
return alphaTex;
|
||||||
@ -58,10 +58,16 @@ namespace AssetStudio
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Image<Bgra32> ApplyRGBMask(Image<Bgra32> tex, Image<Bgra32> texMask)
|
private static void ApplyRGBMask(this Image<Bgra32> tex, Image<Bgra32> texMask, bool isPreview = false)
|
||||||
{
|
{
|
||||||
using (texMask)
|
using (texMask)
|
||||||
{
|
{
|
||||||
|
if (tex.Width != texMask.Width || tex.Height != texMask.Height)
|
||||||
|
{
|
||||||
|
var resampler = isPreview ? KnownResamplers.NearestNeighbor : KnownResamplers.Bicubic;
|
||||||
|
texMask.Mutate(x => x.Resize(tex.Width, tex.Height, resampler));
|
||||||
|
}
|
||||||
|
|
||||||
tex.ProcessPixelRows(texMask, (sourceTex, targetTexMask) =>
|
tex.ProcessPixelRows(texMask, (sourceTex, targetTexMask) =>
|
||||||
{
|
{
|
||||||
for (int y = 0; y < texMask.Height; y++)
|
for (int y = 0; y < texMask.Height; y++)
|
||||||
@ -75,8 +81,6 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return tex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user