32 Commits

Author SHA1 Message Date
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
d9a9e3962f Fix build error on older c# versions.
All checks were successful
Build / build (push) Successful in 1m35s
2024-06-19 11:50:36 +03:00
f976af3833 Increment version counter for 2.0.0-rc
Some checks failed
Build / build (push) Failing after 1m34s
2024-06-19 11:42:29 +03:00
9b21bb837b Move native calls to Stb.Native 2024-06-19 11:31:51 +03:00
e7d7f5f826 Implement stbi_write here. 2024-06-19 11:15:51 +03:00
e0e57b53f4 Increment version counter.
All checks were successful
Build / build (push) Successful in 1m36s
2024-06-16 21:36:11 +03:00
f135a65c96 Add stb_image_write.h support. 2024-06-16 21:34:59 +03:00
846e09054d Pull changes in build_native.sh
All checks were successful
Build / build (push) Successful in 2m0s
2024-06-14 22:11:33 +03:00
722d38be5c Update docker cmakes.
All checks were successful
Build / build (push) Successful in 1m23s
2024-06-14 22:00:20 +03:00
31f5e3938c Increment version.
All checks were successful
Build / build (push) Successful in 1m24s
2024-06-14 21:53:08 +03:00
03ac61a4d2 Fix typo in publish.sh.
All checks were successful
Build / build (push) Successful in 1m18s
2024-06-14 18:51:16 +03:00
9dcd5e56fa Rename API key.
Some checks failed
Build / build (push) Failing after 1m17s
2024-06-14 18:48:41 +03:00
018f195000 Make ci run on push to tag.
Some checks failed
Build / build (push) Failing after 1m20s
2024-06-14 18:44:56 +03:00
13ea2941da fix typo in build script. 2024-06-14 18:43:14 +03:00
0c46adc68b Finish rebranding. 2024-06-14 18:40:36 +03:00
e7c90af3ed Fix build scripts. 2024-06-14 18:32:16 +03:00
112c1065b0 Add license. 2024-06-14 18:28:28 +03:00
ede16bc468 Remove all references to Quik. 2024-06-14 18:24:38 +03:00
6ba91c8808 Added icon.
All checks were successful
Build / build (push) Successful in 1m20s
2024-06-11 19:35:10 +03:00
ecab13f766 Added package icon. 2024-06-11 19:32:42 +03:00
50c2ec73e7 Added package icon.
Some checks failed
Build / build (push) Failing after 1m17s
2024-06-11 19:31:33 +03:00
cb896f9cf3 Added package icon.
Some checks failed
Build / build (push) Failing after 1m17s
2024-06-11 19:26:48 +03:00
8c3e723cac Merge remote-tracking branch 'origin/master'
All checks were successful
Build / build (push) Successful in 1m27s
2024-06-11 19:18:28 +03:00
7f8fad146a Add readme.md 2024-06-11 19:17:51 +03:00
themixedupstuff
23d2ce8087 Macos doesn't have dlls ya silly.
All checks were successful
Build / build (push) Successful in 1m34s
2024-06-07 19:06:52 +02:00
3ee0779d66 Roll over version number.
All checks were successful
Build / build (push) Successful in 1m37s
2024-06-01 14:23:32 +03:00
ec09deb438 Update stb. 2024-06-01 14:22:57 +03:00
07d788da25 Disable all instances of potential thread local storage. 2024-06-01 14:22:41 +03:00
bce883028f Added -static-libstdc++ compile flag.
All checks were successful
Build / build (push) Successful in 1m39s
2024-06-01 11:01:53 +03:00
28 changed files with 840 additions and 157 deletions

View File

@@ -1,19 +1,22 @@
name: Build name: Build
run-name: Building docker container. run-name: Building with docker container.
on: on:
workflow_dispatch: workflow_dispatch:
push: push:
branches: stable tags:
- '*'
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: git.mixedup.dev/quik/docker-cross-compiler image: git.mixedup.dev/refuel/docker-cross-compiler
env: env:
QUIK_API_KEY: "${{secrets.QUIK_API_KEY}}" REFUEL_API_KEY: "${{secrets.REFUEL_API_KEY}}"
NUGET_USER_NAME: "${{vars.NUGET_USER_NAME}}"
NUGET_INDEX: "${{vars.NUGET_INDEX}}"
volumes: volumes:
- ${{ gitea.workspace }}:/home/quik/src - ${{ gitea.workspace }}:/home/refuel/src
steps: steps:
- name: Check repository out. - name: Check repository out.
uses: actions/checkout@v3 uses: actions/checkout@v3

6
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "stb"] [submodule "stb"]
path = stb path = stb
url = https://github.com/nothings/stb.git url = https://github.com/nothings/stb.git
[submodule "Quik.Common"] [submodule "docker-cross-compiler"]
path = Quik.Common path = docker-cross-compiler
url = https://git.mixedup.dev/QUIK/Quik.Common.git url = https://git.mixedup.dev/ReFuel/docker-cross-compiler

47
3RDPARTY.md Normal file
View File

@@ -0,0 +1,47 @@
This package uses 3rd-party software from the following vendors:
-----
* nothings/stb_image.h
* nothigns/stb_image_writer.h
https://raw.githubusercontent.com/nothings/stb/master/LICENSE
This software is available under 2 licenses -- choose whichever you prefer.
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----

View File

@@ -1,12 +1,13 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
project(quik_stbi LANGUAGES C VERSION 1.0) project(rf_stbi LANGUAGES C VERSION 1.0)
if (NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")) if (NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin"))
add_compile_options(-static-libgcc) add_compile_options(-static-libgcc -static-libstdc++ -fno-exceptions)
endif() endif()
add_compile_options(-O3)
add_library(stbi SHARED "quik_stbi.c") add_library(stbi SHARED "rf_stbi.c")
install( install(
TARGETS stbi TARGETS stbi
RUNTIME DESTINATION . RUNTIME DESTINATION .

19
LICENSE.md Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2024 ReFuel.StbImage - H. Utku Maden
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Also see 3RDPARTY.md

View File

@@ -1,6 +1,6 @@
using System; using System;
namespace Quik.Stb.Image namespace Quik.Stb
{ {
[AttributeUsage(System.AttributeTargets.All, Inherited = false, AllowMultiple = true)] [AttributeUsage(System.AttributeTargets.All, Inherited = false, AllowMultiple = true)]
internal sealed class NativeTypeNameAttribute : System.Attribute internal sealed class NativeTypeNameAttribute : System.Attribute

Submodule Quik.Common deleted from fdfac9d951

9
README.md Normal file
View File

@@ -0,0 +1,9 @@
ReFuel.StbImage
=============
ReFuel.StbImage is a binary distribution of the popular stb_image.h single header
library. Existing packages were either bad source ports, had odd wrappers or
weren't up to date.
Originally intended for my own purposes, however feel free to view the code at
https://git.mixedup.dev/ReFuel/ReFuel.StbImage, and shoot me patch files through
email.

View File

@@ -1,22 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<Nullable>disable</Nullable> <Nullable>enable</Nullable>
<LangVersion>7.3</LangVersion> <LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<RuntimeIdentifiers>linux-arm;linux-arm64;linux-x64;win-x86;win-x64;osx-arm64;osx-x64</RuntimeIdentifiers> <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>
<PropertyGroup> <PropertyGroup>
<!-- Nuget Properties. --> <!-- Nuget Properties. -->
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>Quik.StbImage</PackageId> <PackageId>ReFuel.StbImage</PackageId>
<Version>1.1.0</Version> <Version>2.0.1</Version>
<Authors>STBI Authors, H. Utku Maden</Authors> <Authors>STBI Authors, H. Utku Maden</Authors>
<Description> <Description>
A C# wrapper for the ubiquitous Stb Image library. A C# wrapper for the ubiquitous stb_image.h and stb_image_write.h library.
</Description> </Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
<PackageIcon>images\icon.png</PackageIcon>
<PackageProjectUrl>https://refuel.mixedup.dev/docs/ReFuel.StbImage.html</PackageProjectUrl>
<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.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> </PropertyGroup>
<!-- <!--
@@ -26,6 +41,8 @@
that determines a lot of load paths for projects. that determines a lot of load paths for projects.
--> -->
<ItemGroup> <ItemGroup>
<Content Include="*.md" Pack="true" PackagePath="/" />
<None Include="rf_stbimage.png" Pack="true" PackagePath="images\icon.png" />
<Content Include="runtimes/linux-arm/native/*.so"> <Content Include="runtimes/linux-arm/native/*.so">
<PackagePath>runtimes/linux-arm/native/</PackagePath> <PackagePath>runtimes/linux-arm/native/</PackagePath>
<Pack>true</Pack> <Pack>true</Pack>
@@ -56,12 +73,12 @@
<Pack>true</Pack> <Pack>true</Pack>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="runtimes/osx-x64/native/*.dll"> <Content Include="runtimes/osx-x64/native/*.dylib">
<PackagePath>runtimes/osx-x64/native/</PackagePath> <PackagePath>runtimes/osx-x64/native/</PackagePath>
<Pack>true</Pack> <Pack>true</Pack>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="runtimes/osx-arm64/native/*.dll"> <Content Include="runtimes/osx-arm64/native/*.dylib">
<PackagePath>runtimes/osx-arm64/native/</PackagePath> <PackagePath>runtimes/osx-arm64/native/</PackagePath>
<Pack>true</Pack> <Pack>true</Pack>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

View File

@@ -1,25 +1,22 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.5.002.0 VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Quik.StbImage", "Quik.StbImage.csproj", "{C808B4BC-C3AF-4682-8EDA-EAAC780800C3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReFuel.StbImage", "ReFuel.StbImage.csproj", "{413ACBF4-3851-416F-B2A2-F7157EC306B2}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C808B4BC-C3AF-4682-8EDA-EAAC780800C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C808B4BC-C3AF-4682-8EDA-EAAC780800C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C808B4BC-C3AF-4682-8EDA-EAAC780800C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C808B4BC-C3AF-4682-8EDA-EAAC780800C3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
SolutionGuid = {B04E5FBA-41E6-4B0B-BC31-F996BE353F5A} {413ACBF4-3851-416F-B2A2-F7157EC306B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{413ACBF4-3851-416F-B2A2-F7157EC306B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{413ACBF4-3851-416F-B2A2-F7157EC306B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{413ACBF4-3851-416F-B2A2-F7157EC306B2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -1,8 +1,10 @@
using ReFuel.Stb.Native;
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Quik.Stb namespace ReFuel.Stb
{ {
/// <summary> /// <summary>
/// A class that encompasses all features of stb_image.h in a safe way. /// A class that encompasses all features of stb_image.h in a safe way.
@@ -31,6 +33,9 @@ namespace Quik.Stb
/// Internal image format. /// Internal image format.
/// </summary> /// </summary>
public StbiImageFormat Format { get; } public StbiImageFormat Format { get; }
/// <summary>
/// True if the image is a floating point image.
/// </summary>
public bool IsFloat { get; } public bool IsFloat { get; }
private StbImage(IntPtr image, int x, int y, StbiImageFormat format, bool isFloat) private StbImage(IntPtr image, int x, int y, StbiImageFormat format, bool isFloat)
@@ -47,6 +52,71 @@ namespace Quik.Stb
Dispose(false); Dispose(false);
} }
/// <summary>
/// Get a safe span to the image pointer.
/// </summary>
/// <typeparam name="T">The pixel type.</typeparam>
/// <returns>A span to the image data.</returns>
/// <exception cref="Exception">The image uses an unexpected image format.</exception>
public ReadOnlySpan<T> AsSpan<T>() where T : unmanaged
{
int sz = Format switch
{
StbiImageFormat.Grey => 1,
StbiImageFormat.GreyAlpha => 2,
StbiImageFormat.Rgb => 3,
StbiImageFormat.Rgba => 4,
_ => throw new Exception("unkown image format")
} * (IsFloat ? sizeof(float) : sizeof(byte));
return new ReadOnlySpan<T>((T*)ImagePointer, Width * Height * sz / sizeof(T));
}
/// <summary>
/// Write image to a PNG file.
/// </summary>
/// <param name="dest">The destination stream.</param>
/// <remarks>
/// 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>
/// <param name="dest">The destination stream.</param>
/// <remarks>
/// 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>
/// <param name="dest">The destination stream.</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>
public void WriteTga(Stream dest) => WriteTga(AsSpan<byte>(), Width, Height, Format, dest, isFloat: IsFloat);
/// <summary>
/// Write image to a PNG file.
/// </summary>
/// <param name="dest">The destination stream.</param>
/// <remarks>
/// 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>
/// <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>
public void WriteJpg(Stream dest, int quality = 90) => WriteJpg(AsSpan<byte>(), Width, Height, Format, dest, quality: quality, isFloat: IsFloat);
public void Dispose() => Dispose(true); public void Dispose() => Dispose(true);
private void Dispose(bool disposing) private void Dispose(bool disposing)
@@ -65,7 +135,12 @@ namespace Quik.Stb
/// <summary> /// <summary>
/// Set to flip the y-axis of loaded images on load. /// Set to flip the y-axis of loaded images on load.
/// </summary> /// </summary>
public static bool FlipVerticallyOnLoad { set => Stbi.set_flip_vertically_on_load(1); } public static bool FlipVerticallyOnLoad { set => Stbi.set_flip_vertically_on_load(value ? 1 : 0); }
/// <summary>
/// Set to flip the y-axis of saved images.
/// </summary>
public static bool FlipVerticallyOnSave { set => Stbi.flip_vertically_on_write(value ? 1 : 0); }
/// <summary> /// <summary>
/// Set to unpremultiply images on load. /// Set to unpremultiply images on load.
@@ -76,6 +151,50 @@ namespace Quik.Stb
/// </remarks> /// </remarks>
public static bool UnpremultiplyOnLoad { set => Stbi.set_unpremultiply_on_load(1); } public static bool UnpremultiplyOnLoad { set => Stbi.set_unpremultiply_on_load(1); }
/// <summary>
/// Force a filter on PNG filter when saving.
/// </summary>
/// <remarks>
/// -1 for auto, 0 through 5 to pick a filter. Higher is more. Not thread safe.
/// </remarks>
public static int WriteForcePngFilter
{
get => Stbi.write_force_png_filter;
set
{
if (value < -1 || value > 5)
{
throw new ArgumentOutOfRangeException(nameof(value), "The PNG filter must be in the range 0 to 5, or -1 for auto.");
}
Stbi.write_force_png_filter = value;
}
}
/// <summary>
/// Change the PNG compression level on save.
/// </summary>
/// <remarks>
/// Higher is more. Defaults to 8. Not thread safe.
/// </remarks>
public static int WritePngCompressionLevel
{
get => Stbi.write_png_compression_level;
set => Stbi.write_png_compression_level = value;
}
/// <summary>
/// Enable run length encoding on TGA images on save.
/// </summary>
/// <remarks>
/// Not thread safe.
/// </remarks>
public static bool WriteTgaEnableRLE
{
get => Stbi.write_tga_with_rle != 0;
set => Stbi.write_tga_with_rle = value ? 1 : 0;
}
/// <summary> /// <summary>
/// Try loading an image, without raising exceptions. /// Try loading an image, without raising exceptions.
/// </summary> /// </summary>
@@ -83,7 +202,7 @@ namespace Quik.Stb
/// <param name="stream">Source stream.</param> /// <param name="stream">Source stream.</param>
/// <param name="format">The desired image format.</param> /// <param name="format">The desired image format.</param>
/// <returns>True on success.</returns> /// <returns>True on success.</returns>
public static bool TryLoad(out StbImage image, Stream stream, StbiImageFormat format = StbiImageFormat.Default, bool isFloat = false) public static bool TryLoad([NotNullWhen(true)] out StbImage? image, Stream stream, StbiImageFormat format = StbiImageFormat.Default, bool asFloat = false)
{ {
int x, y, iFormat; int x, y, iFormat;
StbiStreamWrapper wrapper = new StbiStreamWrapper(stream, true); StbiStreamWrapper wrapper = new StbiStreamWrapper(stream, true);
@@ -91,7 +210,7 @@ namespace Quik.Stb
stream.Position = 0; stream.Position = 0;
IntPtr imagePtr; IntPtr imagePtr;
if (isFloat) if (asFloat)
{ {
imagePtr = (IntPtr)Stbi.loadf_from_callbacks(&cb, null, &x, &y, &iFormat, (int)format); imagePtr = (IntPtr)Stbi.loadf_from_callbacks(&cb, null, &x, &y, &iFormat, (int)format);
} }
@@ -102,7 +221,7 @@ namespace Quik.Stb
if (imagePtr != IntPtr.Zero) if (imagePtr != IntPtr.Zero)
{ {
image = new StbImage(imagePtr, x, y, (StbiImageFormat)iFormat, isFloat); image = new StbImage(imagePtr, x, y, (StbiImageFormat)iFormat, asFloat);
return true; return true;
} }
else else
@@ -112,24 +231,84 @@ namespace Quik.Stb
} }
} }
/// <summary>
/// Try loading an image, without raising exceptions.
/// </summary>
/// <param name="image">The resulting image.</param>
/// <param name="span">Source memory span.</param>
/// <param name="format">The desired image format.</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)
{
IntPtr imagePtr = IntPtr.Zero;
int x, y, iFormat;
fixed (byte *ptr = MemoryMarshal.AsBytes(span))
{
if (asFloat)
{
imagePtr = (IntPtr)Stbi.loadf_from_memory(ptr, span.Length, &x, &y, &iFormat, (int)format);
}
else
{
imagePtr = (IntPtr)Stbi.load_from_memory(ptr, span.Length, &x, &y, &iFormat, (int)format);
}
if (imagePtr != IntPtr.Zero)
{
image = new StbImage(imagePtr, x, y, (StbiImageFormat)iFormat, asFloat);
return true;
}
else
{
image = null;
return false;
}
}
}
/// <summary> /// <summary>
/// Load an image. /// Load an image.
/// </summary> /// </summary>
/// <param name="stream">The stream to load from.</param> /// <param name="stream">The stream to load from.</param>
/// <param name="format">The desired image format.</param> /// <param name="format">The desired image format.</param>
/// <returns>The image object.</returns> /// <returns>The image object.</returns>
public static StbImage Load(Stream stream, StbiImageFormat format = StbiImageFormat.Default, bool isFloat = false) public static StbImage Load(Stream stream, StbiImageFormat format = StbiImageFormat.Default, bool asFloat = false)
{ {
if (TryLoad(out StbImage image, stream, format, isFloat)) if (TryLoad(out StbImage? image, stream, format, asFloat))
{ {
return image; return image;
} }
string reason = Marshal.PtrToStringUTF8((IntPtr)Stbi.failure_reason()); string reason = Marshal.PtrToStringUTF8((IntPtr)Stbi.failure_reason())!;
throw new Exception($"Failed to load image: {reason}"); throw new Exception($"Failed to load image: {reason}");
} }
public bool IsLoadable(Stream stream) /// <summary>
/// Load an image.
/// </summary>
/// <param name="span">The span of memory to load from.</param>
/// <param name="format">The desired image format.</param>
/// <returns>The image object.</returns>
public static StbImage Load(ReadOnlySpan<byte> span, StbiImageFormat format = StbiImageFormat.Default, bool asFloat = false)
{
if (TryLoad(out StbImage? image, span, format, asFloat))
{
return image;
}
string reason = Marshal.PtrToStringUTF8((IntPtr)Stbi.failure_reason())!;
throw new Exception($"Failed to load image: {reason}");
}
/// <summary>
/// Peek image info from a stream.
/// </summary>
/// <param name="stream">The stream to peek into.</param>
/// <param name="width">Width of the image.</param>
/// <param name="height">Height of the image.</param>
/// <param name="format">The image format.</param>
/// <returns>True if the stream contained an image.</returns>
public static bool PeekInfo(Stream stream, out int width, out int height, out StbiImageFormat format)
{ {
int x, y, iFormat; int x, y, iFormat;
StbiStreamWrapper wrapper = new StbiStreamWrapper(stream, true); StbiStreamWrapper wrapper = new StbiStreamWrapper(stream, true);
@@ -138,7 +317,249 @@ namespace Quik.Stb
stream.Position = 0; stream.Position = 0;
int result = Stbi.info_from_callbacks(&cb, null, &x, &y, &iFormat); int result = Stbi.info_from_callbacks(&cb, null, &x, &y, &iFormat);
width = x;
height = y;
format = (StbiImageFormat)iFormat;
return result != 0;
}
/// <summary>
/// Peek image info from a span.
/// </summary>
/// <param name="span">The span to peek into.</param>
/// <param name="width">Width of the image.</param>
/// <param name="height">Height of the image.</param>
/// <param name="format">The image format.</param>
/// <returns>True if the stream contained an image.</returns>
public static bool PeekInfo<T>(ReadOnlySpan<T> span, out int width, out int height, out StbiImageFormat format) where T : unmanaged
{
fixed (byte* ptr = MemoryMarshal.AsBytes(span))
{
int x, y, iFormat;
int result = Stbi.info_from_memory(ptr, span.Length * sizeof(T), &x, &y, &iFormat);
width = x;
height = y;
format = (StbiImageFormat)iFormat;
return result != 0; return result != 0;
} }
} }
private static int Components(StbiImageFormat format) => format switch
{
StbiImageFormat.Grey => 1,
StbiImageFormat.GreyAlpha => 2,
StbiImageFormat.Rgb => 3,
StbiImageFormat.Rgba => 4,
_ => throw new ArgumentException("Expected a fully qualified format.")
};
private static byte[] ConvertFloatToByte<T>(ReadOnlySpan<T> source, int width, int height, int components)
where T : unmanaged
{
byte[] conversion = new byte[width * height * components];
ReadOnlySpan<float> dataAsFloat = MemoryMarshal.Cast<T, float>(source);
for (int i = 0; i<conversion.Length; i++)
{
conversion[i] = (byte) Math.Clamp(MathF.Round(dataAsFloat[i]* 255), 0, 255);
}
return conversion;
}
private static float[] ConvertByteToFloat<T>(ReadOnlySpan<T> source, int width, int height, int components)
where T : unmanaged
{
float[] conversion = new float[width * height * components];
ReadOnlySpan<byte> dataAsByte = MemoryMarshal.Cast<T, byte>(source);
for (int i = 0; i < conversion.Length; i++)
{
conversion[i] = Math.Clamp(dataAsByte[i]/255f, 0f, 1f);
}
return conversion;
}
/// <summary>
/// Write any image to a PNG file.
/// </summary>
/// <typeparam name="T">Any packed byte or float array structure.</typeparam>
/// <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="destination">The destination stream.</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. Affected by global non-thread safe options.
/// </remarks>
public static void WritePng<T>(ReadOnlySpan<T> data, int width, int height, StbiImageFormat format, Stream destination, bool isFloat = false)
where T : unmanaged
{
int components = Components(format);
ReadOnlySpan<byte> source;
byte[]? conversion;
if (isFloat)
{
conversion = ConvertFloatToByte(data, width, height, components);
source = conversion;
}
else
{
source = MemoryMarshal.AsBytes(data);
}
StbiWriteStreamWrapper wrapper = new StbiWriteStreamWrapper(destination);
fixed (byte *ptr = source)
Stbi.write_png_to_func(wrapper, null, width, height, components, ptr, width * components);
}
/// <summary>
/// Write any image to a BMP file.
/// </summary>
/// <typeparam name="T">Any packed byte or float array structure.</typeparam>
/// <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="destination">The destination stream.</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.
/// </remarks>
public static void WriteBmp<T>(ReadOnlySpan<T> data, int width, int height, StbiImageFormat format, Stream destination, bool isFloat = false)
where T : unmanaged
{
int components = Components(format);
ReadOnlySpan<byte> source;
byte[]? conversion;
if (isFloat)
{
conversion = ConvertFloatToByte(data, width, height, components);
source = conversion;
}
else
{
source = MemoryMarshal.AsBytes(data);
}
StbiWriteStreamWrapper wrapper = new StbiWriteStreamWrapper(destination);
fixed (byte* ptr = source)
Stbi.write_bmp_to_func(wrapper, null, width, height, components, ptr);
}
/// <summary>
/// Write any image to a TGA file.
/// </summary>
/// <typeparam name="T">Any packed byte or float array structure.</typeparam>
/// <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="destination">The destination stream.</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. Affected by global non-thread safe options.
/// </remarks>
public static void WriteTga<T>(ReadOnlySpan<T> data, int width, int height, StbiImageFormat format, Stream destination, bool isFloat = false)
where T : unmanaged
{
int components = Components(format);
ReadOnlySpan<byte> source;
byte[]? conversion;
if (isFloat)
{
conversion = ConvertFloatToByte(data, width, height, components);
source = conversion;
}
else
{
source = MemoryMarshal.AsBytes(data);
}
StbiWriteStreamWrapper wrapper = new StbiWriteStreamWrapper(destination);
fixed (byte* ptr = source)
Stbi.write_tga_to_func(wrapper, null, width, height, components, ptr);
}
/// <summary>
/// Write any image to a PNG file.
/// </summary>
/// <typeparam name="T">Any packed byte or float array structure.</typeparam>
/// <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="destination">The destination stream.</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 float format. Affected by global non-thread safe options.
/// </remarks>
public static void WriteHdr<T>(ReadOnlySpan<T> data, int width, int height, StbiImageFormat format, Stream destination, bool isFloat = false)
where T : unmanaged
{
int components = Components(format);
ReadOnlySpan<float> source;
float[]? conversion;
if (!isFloat)
{
conversion = ConvertByteToFloat(data, width, height, components);
source = conversion;
}
else
{
source = MemoryMarshal.Cast<T, float>(data);
}
StbiWriteStreamWrapper wrapper = new StbiWriteStreamWrapper(destination);
fixed (float* ptr = source)
Stbi.write_hdr_to_func(wrapper, null, width, height, components, ptr);
}
/// <summary>
/// Write any image to a PNG file.
/// </summary>
/// <typeparam name="T">Any packed byte or float array structure.</typeparam>
/// <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="destination">The destination stream.</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.
/// </remarks>
public static void WriteJpg<T>(ReadOnlySpan<T> data, int width, int height, StbiImageFormat format, Stream destination, int quality = 90, bool isFloat = false)
where T : unmanaged
{
int components = Components(format);
ReadOnlySpan<byte> source;
byte[]? conversion;
if (isFloat)
{
conversion = ConvertFloatToByte(data, width, height, components);
source = conversion;
}
else
{
source = MemoryMarshal.AsBytes(data);
}
StbiWriteStreamWrapper wrapper = new StbiWriteStreamWrapper(destination);
fixed (byte* ptr = source)
Stbi.write_jpg_to_func(wrapper, null, width, height, components, ptr, quality);
}
}
} }

View File

@@ -1,14 +1,16 @@
using System; using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Reflection; using System.Reflection;
namespace Quik.Stb namespace ReFuel.Stb.Native
{ {
/// <summary>
/// Direct access to the native STBI function calls.
/// </summary>
public unsafe static partial class Stbi public unsafe static partial class Stbi
{ {
private delegate void FailedAssertProc(byte *expression, byte *file, int line, byte *function); private delegate void FailedAssertProc(byte *expression, byte *file, int line, byte *function);
private static IntPtr stbiHandle;
private static readonly string[] LibraryNames = new string[] private static readonly string[] LibraryNames = new string[]
{ {
@@ -30,37 +32,32 @@ namespace Quik.Stb
{ {
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), Resolver); NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), Resolver);
// quik_stbi_failed_assert_store(Marshal.GetFunctionPointerForDelegate<FailedAssertProc>(FailedAssert)); // Dummy call to fail_reason so we have a handle to STBI.
failure_reason();
// Load global address pointers.
_tga_with_rle_ptr = (int*)NativeLibrary.GetExport(stbiHandle, "stbi_write_tga_with_rle");
_png_compression_level_ptr = (int*)NativeLibrary.GetExport(stbiHandle, "stbi_write_png_compression_level");
_force_png_filter_ptr = (int*)NativeLibrary.GetExport(stbiHandle, "stbi_write_force_png_filter");
} }
private static IntPtr Resolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) private static IntPtr Resolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{ {
if (libraryName != "stbi") if (libraryName != "stbi")
return IntPtr.Zero; return IntPtr.Zero;
else if (stbiHandle != IntPtr.Zero)
return stbiHandle;
foreach (string name in LibraryNames) foreach (string name in LibraryNames)
{ {
if (NativeLibrary.TryLoad(name, assembly, searchPath, out IntPtr handle)) if (NativeLibrary.TryLoad(name, assembly, searchPath, out stbiHandle))
{ {
return handle; return stbiHandle;
} }
} }
return NativeLibrary.Load(libraryName); return stbiHandle = NativeLibrary.Load(libraryName);
}
private static void FailedAssert(byte *expression, byte *file, int line, byte *function)
{
string expr = expression == null ? string.Empty : Marshal.PtrToStringUTF8((IntPtr)expression);
string f = file == null ? string.Empty : Marshal.PtrToStringUTF8((IntPtr)file);
string func = function == null ? string.Empty : Marshal.PtrToStringUTF8((IntPtr)function);
Exception ex = new Exception("Assert failed in native stbi code.");
ex.Data.Add("Expression", expr);
ex.Data.Add("File", f);
ex.Data.Add("Line", line);
ex.Data.Add("Function", func);
throw ex;
} }
} }
} }

97
Stbi.cs
View File

@@ -1,10 +1,8 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Quik.Stb.Image;
namespace Quik.Stb namespace ReFuel.Stb.Native
{ {
[NativeTypeName("unsigned int")]
public enum StbiEnum : uint public enum StbiEnum : uint
{ {
STBI_default = 0, STBI_default = 0,
@@ -16,65 +14,62 @@ namespace Quik.Stb
public partial struct stbi_io_callbacks public partial struct stbi_io_callbacks
{ {
[NativeTypeName("int (*)(void *, char *, int)")]
public IntPtr read; public IntPtr read;
[NativeTypeName("void (*)(void *, int)")]
public IntPtr skip; public IntPtr skip;
[NativeTypeName("int (*)(void *)")]
public IntPtr eof; public IntPtr eof;
} }
public static unsafe partial class Stbi public static unsafe partial class Stbi
{ {
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_memory", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_memory", ExactSpelling = true)]
[return: NativeTypeName("stbi_uc *")]
public static extern byte* load_from_memory([NativeTypeName("const stbi_uc *")] byte* buffer, int len, int* x, int* y, int* channels_in_file, int desired_channels); public static extern byte* load_from_memory(byte* buffer, int len, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_callbacks", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_callbacks", ExactSpelling = true)]
[return: NativeTypeName("stbi_uc *")]
public static extern byte* load_from_callbacks([NativeTypeName("const stbi_io_callbacks *")] stbi_io_callbacks* clbk, void* user, int* x, int* y, int* channels_in_file, int desired_channels); public static extern byte* load_from_callbacks(stbi_io_callbacks* clbk, void* user, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load", ExactSpelling = true)]
[return: NativeTypeName("stbi_uc *")]
public static extern byte* load([NativeTypeName("const char *")] sbyte* filename, int* x, int* y, int* channels_in_file, int desired_channels); public static extern byte* load(sbyte* filename, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_file", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_file", ExactSpelling = true)]
[return: NativeTypeName("stbi_uc *")]
public static extern byte* load_from_file([NativeTypeName("FILE *")] void* f, int* x, int* y, int* channels_in_file, int desired_channels); public static extern byte* load_from_file(void* f, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_gif_from_memory", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_gif_from_memory", ExactSpelling = true)]
[return: NativeTypeName("stbi_uc *")]
public static extern byte* load_gif_from_memory([NativeTypeName("const stbi_uc *")] byte* buffer, int len, int** delays, int* x, int* y, int* z, int* comp, int req_comp); public static extern byte* load_gif_from_memory(byte* buffer, int len, int** delays, int* x, int* y, int* z, int* comp, int req_comp);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_16_from_memory", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_16_from_memory", ExactSpelling = true)]
[return: NativeTypeName("stbi_us *")]
public static extern ushort* load_16_from_memory([NativeTypeName("const stbi_uc *")] byte* buffer, int len, int* x, int* y, int* channels_in_file, int desired_channels); public static extern ushort* load_16_from_memory(byte* buffer, int len, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_16_from_callbacks", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_16_from_callbacks", ExactSpelling = true)]
[return: NativeTypeName("stbi_us *")]
public static extern ushort* load_16_from_callbacks([NativeTypeName("const stbi_io_callbacks *")] stbi_io_callbacks* clbk, void* user, int* x, int* y, int* channels_in_file, int desired_channels); public static extern ushort* load_16_from_callbacks(stbi_io_callbacks* clbk, void* user, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_16", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_16", ExactSpelling = true)]
[return: NativeTypeName("stbi_us *")]
public static extern ushort* load_16([NativeTypeName("const char *")] sbyte* filename, int* x, int* y, int* channels_in_file, int desired_channels); public static extern ushort* load_16(sbyte* filename, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_file_16", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_file_16", ExactSpelling = true)]
[return: NativeTypeName("stbi_us *")]
public static extern ushort* load_from_file_16([NativeTypeName("FILE *")] void* f, int* x, int* y, int* channels_in_file, int desired_channels); public static extern ushort* load_from_file_16(void* f, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_loadf_from_memory", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_loadf_from_memory", ExactSpelling = true)]
public static extern float* loadf_from_memory([NativeTypeName("const stbi_uc *")] byte* buffer, int len, int* x, int* y, int* channels_in_file, int desired_channels); public static extern float* loadf_from_memory(byte* buffer, int len, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_loadf_from_callbacks", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_loadf_from_callbacks", ExactSpelling = true)]
public static extern float* loadf_from_callbacks([NativeTypeName("const stbi_io_callbacks *")] stbi_io_callbacks* clbk, void* user, int* x, int* y, int* channels_in_file, int desired_channels); public static extern float* loadf_from_callbacks(stbi_io_callbacks* clbk, void* user, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_loadf", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_loadf", ExactSpelling = true)]
public static extern float* loadf([NativeTypeName("const char *")] sbyte* filename, int* x, int* y, int* channels_in_file, int desired_channels); public static extern float* loadf(sbyte* filename, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_loadf_from_file", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_loadf_from_file", ExactSpelling = true)]
public static extern float* loadf_from_file([NativeTypeName("FILE *")] void* f, int* x, int* y, int* channels_in_file, int desired_channels); public static extern float* loadf_from_file(void* f, int* x, int* y, int* channels_in_file, int desired_channels);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_hdr_to_ldr_gamma", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_hdr_to_ldr_gamma", ExactSpelling = true)]
public static extern void hdr_to_ldr_gamma(float gamma); public static extern void hdr_to_ldr_gamma(float gamma);
@@ -89,47 +84,47 @@ namespace Quik.Stb
public static extern void ldr_to_hdr_scale(float scale); public static extern void ldr_to_hdr_scale(float scale);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_hdr_from_callbacks", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_hdr_from_callbacks", ExactSpelling = true)]
public static extern int is_hdr_from_callbacks([NativeTypeName("const stbi_io_callbacks *")] stbi_io_callbacks* clbk, void* user); public static extern int is_hdr_from_callbacks(stbi_io_callbacks* clbk, void* user);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_hdr_from_memory", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_hdr_from_memory", ExactSpelling = true)]
public static extern int is_hdr_from_memory([NativeTypeName("const stbi_uc *")] byte* buffer, int len); public static extern int is_hdr_from_memory(byte* buffer, int len);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_hdr", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_hdr", ExactSpelling = true)]
public static extern int is_hdr([NativeTypeName("const char *")] sbyte* filename); public static extern int is_hdr(sbyte* filename);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_hdr_from_file", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_hdr_from_file", ExactSpelling = true)]
public static extern int is_hdr_from_file([NativeTypeName("FILE *")] void* f); public static extern int is_hdr_from_file(void* f);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_failure_reason", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_failure_reason", ExactSpelling = true)]
[return: NativeTypeName("const char *")]
public static extern sbyte* failure_reason(); public static extern sbyte* failure_reason();
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_image_free", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_image_free", ExactSpelling = true)]
public static extern void image_free(void* retval_from_stbi_load); public static extern void image_free(void* retval_from_stbi_load);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_info_from_memory", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_info_from_memory", ExactSpelling = true)]
public static extern int info_from_memory([NativeTypeName("const stbi_uc *")] byte* buffer, int len, int* x, int* y, int* comp); public static extern int info_from_memory(byte* buffer, int len, int* x, int* y, int* comp);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_info_from_callbacks", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_info_from_callbacks", ExactSpelling = true)]
public static extern int info_from_callbacks([NativeTypeName("const stbi_io_callbacks *")] stbi_io_callbacks* clbk, void* user, int* x, int* y, int* comp); public static extern int info_from_callbacks(stbi_io_callbacks* clbk, void* user, int* x, int* y, int* comp);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_16_bit_from_memory", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_16_bit_from_memory", ExactSpelling = true)]
public static extern int is_16_bit_from_memory([NativeTypeName("const stbi_uc *")] byte* buffer, int len); public static extern int is_16_bit_from_memory(byte* buffer, int len);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_16_bit_from_callbacks", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_16_bit_from_callbacks", ExactSpelling = true)]
public static extern int is_16_bit_from_callbacks([NativeTypeName("const stbi_io_callbacks *")] stbi_io_callbacks* clbk, void* user); public static extern int is_16_bit_from_callbacks(stbi_io_callbacks* clbk, void* user);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_info", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_info", ExactSpelling = true)]
public static extern int info([NativeTypeName("const char *")] sbyte* filename, int* x, int* y, int* comp); public static extern int info(sbyte* filename, int* x, int* y, int* comp);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_info_from_file", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_info_from_file", ExactSpelling = true)]
public static extern int info_from_file([NativeTypeName("FILE *")] void* f, int* x, int* y, int* comp); public static extern int info_from_file(void* f, int* x, int* y, int* comp);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_16_bit", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_16_bit", ExactSpelling = true)]
public static extern int is_16_bit([NativeTypeName("const char *")] sbyte* filename); public static extern int is_16_bit(sbyte* filename);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_16_bit_from_file", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_is_16_bit_from_file", ExactSpelling = true)]
public static extern int is_16_bit_from_file([NativeTypeName("FILE *")] void* f); public static extern int is_16_bit_from_file(void* f);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_set_unpremultiply_on_load", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_set_unpremultiply_on_load", ExactSpelling = true)]
public static extern void set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); public static extern void set_unpremultiply_on_load(int flag_true_if_should_unpremultiply);
@@ -150,25 +145,25 @@ namespace Quik.Stb
public static extern void set_flip_vertically_on_load_thread(int flag_true_if_should_flip); public static extern void set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_malloc_guesssize", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_malloc_guesssize", ExactSpelling = true)]
[return: NativeTypeName("char *")]
public static extern sbyte* zlib_decode_malloc_guesssize([NativeTypeName("const char *")] sbyte* buffer, int len, int initial_size, int* outlen); public static extern sbyte* zlib_decode_malloc_guesssize(sbyte* buffer, int len, int initial_size, int* outlen);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_malloc_guesssize_headerflag", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_malloc_guesssize_headerflag", ExactSpelling = true)]
[return: NativeTypeName("char *")]
public static extern sbyte* zlib_decode_malloc_guesssize_headerflag([NativeTypeName("const char *")] sbyte* buffer, int len, int initial_size, int* outlen, int parse_header); public static extern sbyte* zlib_decode_malloc_guesssize_headerflag(sbyte* buffer, int len, int initial_size, int* outlen, int parse_header);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_malloc", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_malloc", ExactSpelling = true)]
[return: NativeTypeName("char *")]
public static extern sbyte* zlib_decode_malloc([NativeTypeName("const char *")] sbyte* buffer, int len, int* outlen); public static extern sbyte* zlib_decode_malloc(sbyte* buffer, int len, int* outlen);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_buffer", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_buffer", ExactSpelling = true)]
public static extern int zlib_decode_buffer([NativeTypeName("char *")] sbyte* obuffer, int olen, [NativeTypeName("const char *")] sbyte* ibuffer, int ilen); public static extern int zlib_decode_buffer(sbyte* ibuffer, int ilen);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_noheader_malloc", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_noheader_malloc", ExactSpelling = true)]
[return: NativeTypeName("char *")]
public static extern sbyte* zlib_decode_noheader_malloc([NativeTypeName("const char *")] sbyte* buffer, int len, int* outlen); public static extern sbyte* zlib_decode_noheader_malloc(sbyte* buffer, int len, int* outlen);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_noheader_buffer", ExactSpelling = true)] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_zlib_decode_noheader_buffer", ExactSpelling = true)]
public static extern int zlib_decode_noheader_buffer([NativeTypeName("char *")] sbyte* obuffer, int olen, [NativeTypeName("const char *")] sbyte* ibuffer, int ilen); public static extern int zlib_decode_noheader_buffer(sbyte* ibuffer, int ilen);
} }
} }

View File

@@ -1,5 +1,10 @@
namespace Quik.Stb using ReFuel.Stb.Native;
namespace ReFuel.Stb
{ {
/// <summary>
/// Enumeration of supported STBI image formats.
/// </summary>
public enum StbiImageFormat public enum StbiImageFormat
{ {
Default = (int)StbiEnum.STBI_default, Default = (int)StbiEnum.STBI_default,

View File

@@ -1,18 +1,46 @@
using ReFuel.Stb.Native;
using System; using System;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Quik.Stb namespace ReFuel.Stb
{ {
/// <summary>
/// Pointer to STBI stream read function.
/// </summary>
/// <param name="userdata">User provided userdata pointer.</param>
/// <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>
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>
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>
public unsafe delegate int StbiEofProc(void *userdata);
/// <summary>
/// An easy to use stream wrapper for use with STBI image load functions.
/// </summary>
public unsafe class StbiStreamWrapper : IDisposable public unsafe class StbiStreamWrapper : IDisposable
{ {
private Stream _stream; private readonly stbi_io_callbacks _callbacks;
private bool _keepOpen; private readonly Stream _stream;
private readonly bool _keepOpen;
private bool _isDisposed; private bool _isDisposed;
private delegate int ReadProc(void *userdata, byte* buffer, int count); private StbiReadProc _readCb;
private delegate void SkipProc(void *userdata, int count); private StbiSkipProc _skipCb;
private delegate int Eof(void *userdata); private StbiEofProc _eofCb;
public ref readonly stbi_io_callbacks Callbacks => ref _callbacks;
public StbiStreamWrapper(Stream stream, bool keepOpen = false) public StbiStreamWrapper(Stream stream, bool keepOpen = false)
{ {
@@ -20,14 +48,23 @@ namespace Quik.Stb
_stream = stream; _stream = stream;
_keepOpen = keepOpen; _keepOpen = keepOpen;
_readCb = ReadCb;
_skipCb = SkipCb;
_eofCb = EofCb;
_callbacks = default;
_callbacks.read = Marshal.GetFunctionPointerForDelegate<StbiReadProc>(_readCb);
_callbacks.skip = Marshal.GetFunctionPointerForDelegate<StbiSkipProc>(_skipCb);
_callbacks.eof = Marshal.GetFunctionPointerForDelegate<StbiEofProc>(_eofCb);
} }
public void CreateCallbacks(out stbi_io_callbacks cb) public void CreateCallbacks(out stbi_io_callbacks cb)
{ {
cb = default; cb = default;
cb.read = Marshal.GetFunctionPointerForDelegate<ReadProc>(ReadCb); cb.read = Marshal.GetFunctionPointerForDelegate<StbiReadProc>(_readCb);
cb.skip = Marshal.GetFunctionPointerForDelegate<SkipProc>(SkipCb); cb.skip = Marshal.GetFunctionPointerForDelegate<StbiSkipProc>(_skipCb);
cb.eof = Marshal.GetFunctionPointerForDelegate<Eof>(EofCb); cb.eof = Marshal.GetFunctionPointerForDelegate<StbiEofProc>(_eofCb);
} }
private int ReadCb(void *userdata, byte* buffer, int count) private int ReadCb(void *userdata, byte* buffer, int count)
@@ -57,4 +94,33 @@ namespace Quik.Stb
_isDisposed = true; _isDisposed = true;
} }
} }
/// <summary>
/// An easy to use stream wrapper for STBI image write functions.
/// </summary>
/// <remarks>Keep object alive for the duration of the write operation.</remarks>
public class StbiWriteStreamWrapper
{
private readonly Stream _stream;
private readonly StbiWriteProc _cb;
public IntPtr Callback { get; }
public StbiWriteStreamWrapper(Stream stream)
{
_stream = stream;
unsafe
{
_cb = WriteCb;
}
Callback = Marshal.GetFunctionPointerForDelegate(_cb);
}
private unsafe void WriteCb(void *context, void *data, int size)
{
_stream.Write(new ReadOnlySpan<byte>((byte*)data, size));
}
public static implicit operator IntPtr(in StbiWriteStreamWrapper wrapper) => wrapper.Callback;
}
} }

56
StbiWrite.cs Normal file
View File

@@ -0,0 +1,56 @@
using System;
using System.Runtime.InteropServices;
namespace ReFuel.Stb.Native
{
/// <summary>
/// Procedure to STBI image write function.
/// </summary>
/// <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>
public unsafe delegate void StbiWriteProc(void* context, void* data, int size);
public unsafe partial class Stbi
{
private static readonly int* _tga_with_rle_ptr;
private static readonly int* _png_compression_level_ptr;
private static readonly int* _force_png_filter_ptr;
public static int write_tga_with_rle
{
get => *_tga_with_rle_ptr;
set => *_tga_with_rle_ptr = value;
}
public static int write_png_compression_level
{
get => *_png_compression_level_ptr;
set => *_png_compression_level_ptr = value;
}
public static int write_force_png_filter
{
get => *_force_png_filter_ptr;
set => *_force_png_filter_ptr = value;
}
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_write_png_to_func")]
public static extern int write_png_to_func(IntPtr func, void* context, int w, int h, int comp, void* data, int stride_in_bytes);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_write_bmp_to_func")]
public static extern int write_bmp_to_func(IntPtr func, void* context, int w, int h, int comp, void* data);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_write_tga_to_func")]
public static extern int write_tga_to_func(IntPtr func, void* context, int w, int h, int comp, void* data);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_write_hdr_to_func")]
public static extern int write_hdr_to_func(IntPtr func, void* context, int w, int h, int comp, void* data);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_write_jpg_to_func")]
public static extern int write_jpg_to_func(IntPtr func, void* context, int w, int h, int comp, void* data, int quality);
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_flip_vertically_on_write")]
public static extern int flip_vertically_on_write(int value);
}
}

View File

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

View File

@@ -2,15 +2,15 @@ version: "2"
services: services:
build: build:
image: git.mixedup.dev/quik/docker-cross-compiler image: git.mixedup.dev/refuel/docker-cross-compiler
command: "/home/quik/src/build_native.sh" command: "/home/refuel/src/build_native.sh"
volumes: volumes:
- .:/home/quik/src - .:/home/refuel/src
publish: publish:
image: git.mixedup.dev/quik/docker-cross-compiler image: git.mixedup.dev/refuel/docker-cross-compiler
command: "/home/quik/src/publish.sh" command: "/home/refuel/src/publish.sh"
environment: environment:
QUIK_API_KEY: ${QUIK_API_KEY} QUIK_API_KEY: ${QUIK_API_KEY}
volumes: volumes:
- .:/home/quik/src - .:/home/refuel/src

1
docker-cross-compiler Submodule

Submodule docker-cross-compiler added at d0f5760c7a

View File

@@ -1,14 +1,27 @@
#!/bin/bash #!/bin/bash
cd $(dirname "$0") cd $(dirname "$0")
if [ -z "$QUIK_API_KEY" ]
if [ -z "$REFUEL_API_KEY" ]
then then
echo "Please define QUIK_API_KEY" echo "Please define REFUEL_API_KEY"
exit 1
fi
if [ -z "$NUGET_USER_NAME" ]
then
echo "Please define NUGET_USER_NAME"
exit 1
fi
if [ -z "$NUGET_INDEX" ]
then
echo "Please define NUGET_INDEX"
exit 1 exit 1
fi fi
dotnet nuget add source \ dotnet nuget add source \
-n QUIK -u themixedupstuff -p "$QUIK_API_KEY" \ -n ReFuel -u "$NUGET_USER_NAME" -p "$REFUEL_API_KEY" \
--store-password-in-clear-text \ --store-password-in-clear-text \
https://git.mixedup.dev/api/packages/QUIK/nuget/index.json "$NUGET_INDEX"
dotnet nuget push -s QUIK bin/*/*.nupkg dotnet nuget push -s ReFuel bin/*/*.nupkg

View File

@@ -1,4 +0,0 @@
#include "quik_stbi.h"
#define STB_IMAGE_IMPLEMENTATION 1
#include "stb/stb_image.h"

View File

@@ -1,10 +0,0 @@
#ifndef _QUIK_STBI_H_
#define _QUIK_STBI_H_
#include "Quik.Common/include/quik_common.h"
#define STBIDEF QEXTERN
#include "stb/stb_image.h"
#endif

7
rf_stbi.c Normal file
View File

@@ -0,0 +1,7 @@
#include "rf_stbi.h"
#define STB_IMAGE_IMPLEMENTATION 1
#include "stb/stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION 1
#include "stb/stb_image_write.h"

14
rf_stbi.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef _REFUEL_STBI_H_
#define _REFUEL_STBI_H_
#include "docker-cross-compiler/include/rf_common.h"
#define STBIDEF RFEXTERN
#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"
#endif

BIN
rf_stbimage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

2
stb

Submodule stb updated: ae721c50ea...f7f20f39fe

View File

@@ -10,18 +10,18 @@
generate-setslastsystemerror-attribute generate-setslastsystemerror-attribute
unix-types unix-types
--include-directory --include-directory
../lib stb
--include-directory --include-directory
../Quik.StbImage .
--include-directory --include-directory
/usr/lib/llvm-14/lib/clang/14.0.6/include /usr/lib/llvm-14/lib/clang/14.0.6/include
--file --file
../Quik.StbImage.redist/quik_stbi.h rf_stbi.h
../lib/stb/stb_image.h stb/stb_image.h
--methodClassName --methodClassName
Stbi Stbi
--namespace --namespace
Quik.Stb ReFuel.Stb
--output --output
Stbi.cs Stbi.cs
--prefixStrip --prefixStrip

30
stb_image_write.rsp Normal file
View File

@@ -0,0 +1,30 @@
-x
c
-l
stbi
--config
compatible-codegen
single-file
exclude-fnptr-codegen
generate-aggressive-inlining
generate-setslastsystemerror-attribute
unix-types
--include-directory
stb
--include-directory
.
--include-directory
/usr/lib/llvm-14/lib/clang/14.0.6/include
--file
rf_stbi.h
stb/stb_image_write.h
--methodClassName
StbiWrite
--namespace
ReFuel.Stb
--output
StbiWrite.cs
--prefixStrip
stbi_write_
--with-type
FILE=void