YAPF/docs/LANGUAGES.md
Nexoniarz d7f494a0c9 Language bindings, KDE thumbnails, yapf compare, in-memory encoding
- yapf_encode() / yapf_free_buffer(): encode to memory; yapf_save uses it
- yapf.c also compiles as C++
- `yapf compare`: size and decode speed of the original format vs YAPF,
  with a lossless check
- bindings with tested examples: C++ (header-only), C# (P/Invoke),
  Rust (crate, builds the C code), Go (cgo), Java (FFM API, Java 22+),
  Zig (@cImport), LuaJIT (FFI), TypeScript types for the JS port;
  Python now encodes in memory
- docs/LANGUAGES.md and examples/ with measured results
- KDE Dolphin thumbnail plugin (KF6, CMake)
- README: honest status for Photoshop / VS Code / Figma (not run in the
  apps yet) and macOS (cross-compiled only), platform table

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:39:56 +02:00

5.2 KiB
Raw Blame History

Using YAPF from your language

YAPF is a small C library with six functions, so every language that can call C can use it. Ready-made bindings, each with a runnable example:

Language Folder How it works Tested Decode¹
C yapf.h, examples/c the library itself ✅ 0.26 ms
C++ bindings/cpp header-only RAII wrapper (C++17) ✅ g++ 0.25 ms
Python bindings/python ctypes; numpy fallback without the library ✅ CPython 3.13 0.23 ms
C# / .NET bindings/csharp P/Invoke, single file ✅ .NET 8 0.30 ms
Rust bindings/rust crate, builds the C code with cc ✅ Rust 1.95 0.28 ms
Go bindings/go cgo package ✅ Go 1.26 0.31 ms
Java / Kotlin bindings/java Foreign Function & Memory API (Java 22+) ✅ JDK 25 0.42 ms
Zig bindings/zig @cImport of yapf.h ✅ Zig 0.16 0.28 ms
Lua bindings/lua LuaJIT FFI (also LÖVE) ✅ LuaJIT 2.1 0.28 ms
JavaScript / TypeScript bindings/js pure JS port, .d.ts types ✅ Node 24, Chromium 5.9 ms

¹ Decoding the 512×512 RGBA YAPF logo (other/YAPF.YAPF), best of 10 after a warm-up, on an AMD Ryzen 7 5700G. Every binding except JavaScript runs the same native code, so they are all about equally fast; the JavaScript port needs no native library at all. Every example also re-encodes the image and checks that the result is byte-identical to the original file.

Getting the native library

Bindings other than C, C++, Rust, Go, Zig and JavaScript load the shared library at run time:

System File Get it
Windows yapf.dll Releases or build.bat
Linux libyapf.so Releases, make, or sudo make install
macOS libyapf.dylib Releases or make

Put it next to your program, on the library path (PATH, LD_LIBRARY_PATH, DYLD_LIBRARY_PATH), or pass its path explicitly (YAPF_LIBRARY for Python and Lua, -Dyapf.library= for Java).

Quick look

C

yapf_image_t *img = yapf_load("texture.yapf");
/* img->width, img->height, img->channels, img->pixels */
yapf_free(img);

C++

auto img = yapf::Image::load("texture.yapf");
auto bytes = img.encode();

Python

img = yapf.load("texture.yapf")
yapf.save("copy.yapf", img)

C#

var img = YapfImage.Load("texture.yapf");
File.WriteAllBytes("copy.yapf", img.Encode());

Rust

let img = yapf::Image::load("texture.yapf")?;
img.save("copy.yapf")?;

Go

img, err := yapf.Load("texture.yapf")
data, err := yapf.Encode(img)

Java

Yapf.Image img = Yapf.load(Path.of("texture.yapf"));
Yapf.save(Path.of("copy.yapf"), img);

Zig

const img = c.yapf_load("texture.yapf") orelse return error.CannotLoad;
defer c.yapf_free(img);

Lua

local img = yapf.load("texture.yapf")
yapf.save("copy.yapf", img)

JavaScript

const img = YAPF.decode(bytes);
const file = YAPF.encode(img);

Any other language

Swift, Kotlin/Native, Dart, PHP, Ruby, Julia, Nim, D, Odin, Haskell, … — anything with a C foreign-function interface can call the library directly. These are the whole API:

typedef struct {
    uint32_t  width, height;
    uint8_t   channels;     /* 1 gray, 2 gray+alpha, 3 RGB, 4 RGBA */
    uint8_t   gpu_format;   /* hint, see yapf.h */
    uint8_t   flags;        /* 1 premultiplied alpha, 2 sRGB */
    uint8_t   mip_levels;
    uint8_t  *pixels;       /* width*height*channels bytes, rows top to bottom */
    uint8_t **mips;         /* mips[0] == pixels */
} yapf_image_t;             /* 32 bytes on 64-bit systems: pixels at offset 16, mips at 24 */

yapf_image_t *yapf_load_memory_mt(const void *data, size_t size, int threads);  /* threads: 1 or 0 = all cores */
void          yapf_free(yapf_image_t *img);
int           yapf_encode(const yapf_image_t *img, void **out_data, size_t *out_size);
void          yapf_free_buffer(void *data);
yapf_image_t *yapf_load(const char *path);
int           yapf_save(const char *path, const yapf_image_t *img);

Returned images and buffers must be released with yapf_free / yapf_free_buffer from the same library. Ready-made bindings for these languages are not included yet; the snippets below show the starting point and are not tested.

Swift — add a module map for yapf.h (or a bridging header) and compile yapf.c in the target; then let img = yapf_load(path) works as is.

Dart — dart:ffi: DynamicLibrary.open('libyapf.so') and lookupFunction<Pointer<YapfImage> Function(Pointer<Uint8>, IntPtr, Int32), …>('yapf_load_memory_mt').

PHP 7.4+ — $ffi = FFI::cdef(file_get_contents('yapf_api.h'), 'libyapf.so'); with the declarations above in yapf_api.h.

Ruby — Fiddle::Function.new(lib['yapf_load'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP).

Julia — ccall((:yapf_load, "libyapf"), Ptr{Cvoid}, (Cstring,), path).