Use StbImageWriteSharp instead of System.Drawing.Common

* Resolves #1631
This commit is contained in:
ds5678 2025-01-13 17:25:38 -08:00
parent cc95f8a6d8
commit 2132a7113d
4 changed files with 23 additions and 61 deletions

View File

@ -19,7 +19,6 @@
<PackageReference Include="Kyaru.Texture2DDecoder.macOS" Version="0.1.0" />
<PackageReference Include="Kyaru.Texture2DDecoder.Linux" Version="0.1.0" />
<PackageReference Include="StbImageWriteSharp" Version="1.16.7" />
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
</ItemGroup>
<ItemGroup>

View File

@ -19,7 +19,7 @@ public abstract class DirectBitmap
ArgumentOutOfRangeException.ThrowIfNegative(height);
ArgumentOutOfRangeException.ThrowIfNegative(depth);
long byteSize = CalculateByteSize(width, height, depth, PixelSize);
ArgumentOutOfRangeException.ThrowIfGreaterThan(byteSize, int.MaxValue);
ArgumentOutOfRangeException.ThrowIfGreaterThan(byteSize, Array.MaxLength);
Width = width;
Height = height;
Depth = depth;
@ -47,6 +47,8 @@ public abstract class DirectBitmap
}
}
public abstract DirectBitmap GetLayer(int layer);
public abstract void FlipX();
public abstract void FlipY();

View File

@ -2,11 +2,8 @@ using AssetRipper.TextureDecoder.Exr;
using AssetRipper.TextureDecoder.Rgb;
using AssetRipper.TextureDecoder.Rgb.Formats;
using StbImageWriteSharp;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace AssetRipper.Export.Modules.Textures;
@ -28,6 +25,18 @@ public sealed class DirectBitmap<TColor, TChannel> : DirectBitmap
{
}
public override DirectBitmap<TColor, TChannel> GetLayer(int layer)
{
ArgumentOutOfRangeException.ThrowIfNegative(layer);
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(layer, Depth);
int layerSize = Width * Height;
byte[] layerData = new byte[layerSize * PixelSize];
Buffer.BlockCopy(Data, layer * layerSize * PixelSize, layerData, 0, layerSize * PixelSize);
return new DirectBitmap<TColor, TChannel>(Width, Height, 1, layerData);
}
public override void FlipX()
{
int totalRows = Height * Depth;
@ -89,10 +98,6 @@ public sealed class DirectBitmap<TColor, TChannel> : DirectBitmap
{
BmpWriter.WriteBmp(Data, Width, Height * Depth, stream);
}
else if (OperatingSystem.IsWindows())
{
SaveUsingSystemDrawing(stream, ImageFormat.Bmp);
}
else
{
GetDataAndComponentsForSaving(out byte[] data, out ColorComponents components);
@ -119,33 +124,19 @@ public sealed class DirectBitmap<TColor, TChannel> : DirectBitmap
public override void SaveAsJpeg(Stream stream)
{
if (OperatingSystem.IsWindows())
GetDataAndComponentsForSaving(out byte[] data, out ColorComponents components);
lock (imageWriter)
{
SaveUsingSystemDrawing(stream, ImageFormat.Jpeg);
}
else
{
GetDataAndComponentsForSaving(out byte[] data, out ColorComponents components);
lock (imageWriter)
{
imageWriter.WriteJpg(data, Width, Height * Depth, components, stream, default);
}
imageWriter.WriteJpg(data, Width, Height * Depth, components, stream, default);
}
}
public override void SaveAsPng(Stream stream)
{
if (OperatingSystem.IsWindows())
GetDataAndComponentsForSaving(out byte[] data, out ColorComponents components);
lock (imageWriter)
{
SaveUsingSystemDrawing(stream, ImageFormat.Png);
}
else
{
GetDataAndComponentsForSaving(out byte[] data, out ColorComponents components);
lock (imageWriter)
{
imageWriter.WritePng(data, Width, Height * Depth, components, stream);
}
imageWriter.WritePng(data, Width, Height * Depth, components, stream);
}
}
@ -181,36 +172,4 @@ public sealed class DirectBitmap<TColor, TChannel> : DirectBitmap
components = ColorComponents.RedGreenBlue;
}
}
[SupportedOSPlatform("windows")]
private void SaveUsingSystemDrawing(Stream stream, ImageFormat format)
{
GetData(this, out byte[] data, out int pixelSize, out PixelFormat pixelFormat);
GCHandle bitsHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
using Bitmap bitmap = new Bitmap(Width, Height * Depth, Width * pixelSize, pixelFormat, bitsHandle.AddrOfPinnedObject());
bitmap.Save(stream, format);
}
finally
{
bitsHandle.Free();
}
static void GetData(DirectBitmap<TColor, TChannel> @this, out byte[] data, out int pixelSize, out PixelFormat pixelFormat)
{
if (typeof(TColor) == typeof(ColorBGRA32))
{
data = @this.Data;
pixelSize = 4;
pixelFormat = PixelFormat.Format32bppArgb;
}
else
{
RgbConverter.Convert<TColor, TChannel, ColorBGRA32, byte>(@this.Bits, @this.Width, @this.Height * @this.Depth, out data);
pixelSize = 4;
pixelFormat = PixelFormat.Format32bppArgb;
}
}
}
}

View File

@ -10,6 +10,8 @@ internal sealed class EmptyDirectBitmap : DirectBitmap
public override int PixelSize => 0;
public override EmptyDirectBitmap GetLayer(int layer) => this;
public override void FlipX()
{
}