10 Commits

Author SHA1 Message Date
6ffcd38cbc Add GCHandle to StbiStreamWrapper in TryLoad routines.
All checks were successful
Build / build (push) Successful in 1m56s
2024-11-18 20:17:31 +03:00
09b5238b24 Bump version and release notes.
All checks were successful
Build / build (push) Successful in 2m5s
2024-11-18 19:59:29 +03:00
7157db6bd0 Additional documentation. 2024-11-18 19:57:50 +03:00
df61cdc5aa Fix bug in UnpremultiplyOnLoad. 2024-11-18 19:57:38 +03:00
50c37e58fc Add calling convention attributes to unmanaged function pointers. 2024-11-18 19:33:28 +03:00
8e8c86b2c1 Remove unnecessary attribute. 2024-11-18 19:32:23 +03:00
ff83cb20f9 Enabled optimzations.
All checks were successful
Build / build (push) Successful in 2m2s
2024-07-23 23:21:12 +03:00
themixedupstuff
3801bc29f8 Update ReFuel.StbImage.csproj
All checks were successful
Build / build (push) Successful in 1m36s
2024-06-29 13:34:59 +02:00
bcd82900c7 Add STBIWDEF as RFEXTERN to build C file.
All checks were successful
Build / build (push) Successful in 1m35s
2024-06-19 12:19:33 +03:00
e759efacf6 [2.0.0-rc.2] Fix global options to be static.
All checks were successful
Build / build (push) Successful in 1m37s
2024-06-19 12:05:54 +03:00
10 changed files with 52 additions and 39 deletions

View File

@@ -5,9 +5,10 @@ project(rf_stbi LANGUAGES C VERSION 1.0)
if (NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin"))
add_compile_options(-static-libgcc -static-libstdc++ -fno-exceptions)
endif()
add_compile_options(-O3)
add_library(stbi SHARED "rf_stbi.c")
install(
install(
TARGETS stbi
RUNTIME DESTINATION .
LIBRARY DESTINATION .)

View File

@@ -1,12 +0,0 @@
using System;
namespace Quik.Stb
{
[AttributeUsage(System.AttributeTargets.All, Inherited = false, AllowMultiple = true)]
internal sealed class NativeTypeNameAttribute : System.Attribute
{
public NativeTypeNameAttribute(string typename)
{
}
}
}

View File

@@ -1,19 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<RuntimeIdentifiers>linux-arm;linux-arm64;linux-x64;win-x86;win-x64;osx-arm64;osx-x64</RuntimeIdentifiers>
<RootNamespace>ReFuel.Stb</RootNamespace>
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup>
<!-- Nuget Properties. -->
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>ReFuel.StbImage</PackageId>
<Version>2.0-rc</Version>
<Version>2.0.2-rc.1</Version>
<Authors>STBI Authors, H. Utku Maden</Authors>
<Description>
A C# wrapper for the ubiquitous stb_image.h and stb_image_write.h library.
@@ -25,7 +26,15 @@
<RepositoryUrl>https://git.mixedup.dev/ReFuel/ReFuel.StbImage</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>stb; stb_image; stbi; image; load; save; read; write</PackageTags>
<PackageReleaseNotes># 2.0.0
<PackageReleaseNotes># 2.0.2
* Fixed calling convention of unmanaged function pointers. (Thanks NogginBops!)
* Allocating a GC handle to StbiStreamWrapper class and passing it as userdata into stbi in order to prevent
the object from being prematurely collected by the garbage collector when optimizations are enabled in Release mode.
# 2.0.1
* Enabled optimizations across the board for native and managed assemblies.
# 2.0.0
* Exposed stbi_image_write.h
* Moved native function calls to ReFuel.Stb.Native</PackageReleaseNotes>
</PropertyGroup>

View File

@@ -33,6 +33,7 @@ namespace ReFuel.Stb
/// Internal image format.
/// </summary>
public StbiImageFormat Format { get; }
/// <summary>
/// True if the image is a floating point image.
/// </summary>
@@ -66,7 +67,7 @@ namespace ReFuel.Stb
StbiImageFormat.GreyAlpha => 2,
StbiImageFormat.Rgb => 3,
StbiImageFormat.Rgba => 4,
_ => throw new Exception("unkown image format")
_ => throw new Exception("unknown image format")
} * (IsFloat ? sizeof(float) : sizeof(byte));
return new ReadOnlySpan<T>((T*)ImagePointer, Width * Height * sz / sizeof(T));
@@ -80,7 +81,7 @@ namespace ReFuel.Stb
/// Incurs a conversion cost if the image format is not a byte format. Affected by non-thread safe global options.
/// </remarks>
public void WritePng(Stream dest) => WritePng(AsSpan<byte>(), Width, Height, Format, dest, isFloat: IsFloat);
/// <summary>
/// Write image to a BMP file.
/// </summary>
@@ -89,7 +90,7 @@ namespace ReFuel.Stb
/// Incurs a conversion cost if the image format is not a byte format. Affected by non-thread safe global options.
/// </remarks>
public void WriteBmp(Stream dest) => WriteBmp(AsSpan<byte>(), Width, Height, Format, dest, isFloat: IsFloat);
/// <summary>
/// Write image to a TGA file.
/// </summary>
@@ -98,7 +99,7 @@ namespace ReFuel.Stb
/// Incurs a conversion cost if the image format is not a byte format. Ignores alpha channel. Affected by non-thread safe global options.
/// </remarks>
public void WriteTga(Stream dest) => WriteTga(AsSpan<byte>(), Width, Height, Format, dest, isFloat: IsFloat);
/// <summary>
/// Write image to a PNG file.
/// </summary>
@@ -107,11 +108,12 @@ namespace ReFuel.Stb
/// Incurs a conversion cost if the image format is not a float format. Affected by non-thread safe global options.
/// </remarks>
public void WriteHdr(Stream dest) => WriteHdr(AsSpan<byte>(), Width, Height, Format, dest, isFloat: IsFloat);
/// <summary>
/// Write image to a PNG file.
/// </summary>
/// <param name="dest">The destination stream.</param>
/// <param name="quality">The JPEG quality factor.</param>
/// <remarks>
/// Incurs a conversion cost if the image format is not a byte format. Ignores alpha channel. Affected by non-thread safe global options.
/// </remarks>
@@ -149,7 +151,7 @@ namespace ReFuel.Stb
/// According to the stb_image documentation, only iPhone PNG images
/// can come with premultiplied alpha.
/// </remarks>
public static bool UnpremultiplyOnLoad { set => Stbi.set_unpremultiply_on_load(1); }
public static bool UnpremultiplyOnLoad { set => Stbi.set_unpremultiply_on_load(value ? 1 : 0); }
/// <summary>
/// Force a filter on PNG filter when saving.
@@ -157,7 +159,7 @@ namespace ReFuel.Stb
/// <remarks>
/// -1 for auto, 0 through 5 to pick a filter. Higher is more. Not thread safe.
/// </remarks>
public int WriteForcePngFilter
public static int WriteForcePngFilter
{
get => Stbi.write_force_png_filter;
set
@@ -177,7 +179,7 @@ namespace ReFuel.Stb
/// <remarks>
/// Higher is more. Defaults to 8. Not thread safe.
/// </remarks>
public int WritePngCompressionLevel
public static int WritePngCompressionLevel
{
get => Stbi.write_png_compression_level;
set => Stbi.write_png_compression_level = value;
@@ -189,7 +191,7 @@ namespace ReFuel.Stb
/// <remarks>
/// Not thread safe.
/// </remarks>
public bool WriteTgaEnableRLE
public static bool WriteTgaEnableRLE
{
get => Stbi.write_tga_with_rle != 0;
set => Stbi.write_tga_with_rle = value ? 1 : 0;
@@ -201,23 +203,25 @@ namespace ReFuel.Stb
/// <param name="image">The resulting image.</param>
/// <param name="stream">Source stream.</param>
/// <param name="format">The desired image format.</param>
/// <param name="asFloat">The buffer uses floating point pixels if true.</param>
/// <returns>True on success.</returns>
public static bool TryLoad([NotNullWhen(true)] out StbImage? image, Stream stream, StbiImageFormat format = StbiImageFormat.Default, bool asFloat = false)
{
int x, y, iFormat;
StbiStreamWrapper wrapper = new StbiStreamWrapper(stream, true);
GCHandle gch = GCHandle.Alloc(wrapper, GCHandleType.Normal);
wrapper.CreateCallbacks(out stbi_io_callbacks cb);
stream.Position = 0;
IntPtr imagePtr;
if (asFloat)
{
imagePtr = (IntPtr)Stbi.loadf_from_callbacks(&cb, null, &x, &y, &iFormat, (int)format);
imagePtr = (IntPtr)Stbi.loadf_from_callbacks(&cb, (void*)(IntPtr)gch, &x, &y, &iFormat, (int)format);
}
else
{
imagePtr = (IntPtr)Stbi.load_from_callbacks(&cb, null, &x, &y, &iFormat, (int)format);
imagePtr = (IntPtr)Stbi.load_from_callbacks(&cb, (void*)(IntPtr)gch, &x, &y, &iFormat, (int)format);
}
gch.Free();
if (imagePtr != IntPtr.Zero)
{
@@ -237,6 +241,7 @@ namespace ReFuel.Stb
/// <param name="image">The resulting image.</param>
/// <param name="span">Source memory span.</param>
/// <param name="format">The desired image format.</param>
/// <param name="asFloat">The buffer uses floating point pixels if true.</param>
/// <returns>True on success.</returns>
public static bool TryLoad([NotNullWhen(true)] out StbImage? image, ReadOnlySpan<byte> span, StbiImageFormat format = StbiImageFormat.Default, bool asFloat = false)
{
@@ -271,6 +276,7 @@ namespace ReFuel.Stb
/// </summary>
/// <param name="stream">The stream to load from.</param>
/// <param name="format">The desired image format.</param>
/// <param name="asFloat">The buffer uses floating point pixels if true.</param>
/// <returns>The image object.</returns>
public static StbImage Load(Stream stream, StbiImageFormat format = StbiImageFormat.Default, bool asFloat = false)
{
@@ -288,6 +294,7 @@ namespace ReFuel.Stb
/// </summary>
/// <param name="span">The span of memory to load from.</param>
/// <param name="format">The desired image format.</param>
/// <param name="asFloat">The buffer uses floating point pixels if true.</param>
/// <returns>The image object.</returns>
public static StbImage Load(ReadOnlySpan<byte> span, StbiImageFormat format = StbiImageFormat.Default, bool asFloat = false)
{
@@ -389,7 +396,7 @@ namespace ReFuel.Stb
/// <param name="data">Span of pixel data.</param>
/// <param name="width">Width of the pixel data in pixels.</param>
/// <param name="height">Height of the pixel data in pixels.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat.StbiImageFormat"/>.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat"/>.</param>
/// <param name="destination">The destination stream.</param>
/// <param name="isFloat">True if the pixel format in data is a floating point format.</param>
/// <remarks>
@@ -425,7 +432,7 @@ namespace ReFuel.Stb
/// <param name="data">Span of pixel data.</param>
/// <param name="width">Width of the pixel data in pixels.</param>
/// <param name="height">Height of the pixel data in pixels.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat.StbiImageFormat"/>.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat"/>.</param>
/// <param name="destination">The destination stream.</param>
/// <param name="isFloat">True if the pixel format in data is a floating point format.</param>
/// <remarks>
@@ -461,7 +468,7 @@ namespace ReFuel.Stb
/// <param name="data">Span of pixel data.</param>
/// <param name="width">Width of the pixel data in pixels.</param>
/// <param name="height">Height of the pixel data in pixels.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat.StbiImageFormat"/>.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat"/>.</param>
/// <param name="destination">The destination stream.</param>
/// <param name="isFloat">True if the pixel format in data is a floating point format.</param>
/// <remarks>
@@ -497,7 +504,7 @@ namespace ReFuel.Stb
/// <param name="data">Span of pixel data.</param>
/// <param name="width">Width of the pixel data in pixels.</param>
/// <param name="height">Height of the pixel data in pixels.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat.StbiImageFormat"/>.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat"/>.</param>
/// <param name="destination">The destination stream.</param>
/// <param name="isFloat">True if the pixel format in data is a floating point format.</param>
/// <remarks>
@@ -533,8 +540,9 @@ namespace ReFuel.Stb
/// <param name="data">Span of pixel data.</param>
/// <param name="width">Width of the pixel data in pixels.</param>
/// <param name="height">Height of the pixel data in pixels.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat.StbiImageFormat"/>.</param>
/// <param name="format">Color format of the pixel data. Must not be <see cref="StbiImageFormat"/>.</param>
/// <param name="destination">The destination stream.</param>
/// <param name="quality">The JPEG quality factor.</param>
/// <param name="isFloat">True if the pixel format in data is a floating point format.</param>
/// <remarks>
/// This will incur a conversion cost if the pixel format is not a byte format. Ignores the alpha channel. Affected by global non-thread safe options.
@@ -562,4 +570,4 @@ namespace ReFuel.Stb
Stbi.write_jpg_to_func(wrapper, null, width, height, components, ptr, quality);
}
}
}
}

View File

@@ -12,18 +12,23 @@ namespace ReFuel.Stb
/// <param name="buffer">C array to read into.</param>
/// <param name="count">Size of the C array in bytes.</param>
/// <returns>The number of bytes read from the stream.</returns>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate int StbiReadProc(void *userdata, byte* buffer, int count);
/// <summary>
/// Pointer to STBI stream skip function.
/// </summary>
/// <param name="userdata">User provided userdata pointer.</param>
/// <param name="count">Number of bytes to skip.</param>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate void StbiSkipProc(void *userdata, int count);
/// <summary>
/// Pointer to STBI stream end of file function.
/// </summary>
/// <param name="userdata">User provided userdata pointer.</param>
/// <returns>Non-zero value if the end of the stream has been reached.</returns>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate int StbiEofProc(void *userdata);
/// <summary>
@@ -123,4 +128,4 @@ namespace ReFuel.Stb
public static implicit operator IntPtr(in StbiWriteStreamWrapper wrapper) => wrapper.Callback;
}
}
}

View File

@@ -9,6 +9,7 @@ namespace ReFuel.Stb.Native
/// <param name="context">User provided context pointer.</param>
/// <param name="data">C Array of data to write.</param>
/// <param name="size">Size of the C array in bytes.</param>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate void StbiWriteProc(void* context, void* data, int size);
public unsafe partial class Stbi
@@ -24,7 +25,7 @@ namespace ReFuel.Stb.Native
}
public static int write_png_compression_level
{
{
get => *_png_compression_level_ptr;
set => *_png_compression_level_ptr = value;
}

View File

@@ -1,4 +1,4 @@
#!/bin/bash
cd $(dirname "$0")
./docker-cross-compiler/sh/build_native.sh .
dotnet build
dotnet build -c Release

View File

@@ -7,6 +7,7 @@
#define STBI_NO_THREAD_LOCALS 1
#include "stb/stb_image.h"
#define STBIWDEF RFEXTERN
#define STBI_WRITE_NO_STDIO 1
#include "stb/stb_image_write.h"

2
stb

Submodule stb updated: 013ac3bedd...f7f20f39fe