Skip to content

Commit

Permalink
Exploring what a helper module might look like (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
lopcode authored Aug 18, 2024
1 parent 7e8a7ae commit b962f04
Show file tree
Hide file tree
Showing 96 changed files with 26,180 additions and 21,349 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# vips-ffm

[libvips](https://github.com/libvips/libvips) bindings for JVM projects, using the "Foreign Function & Memory API"
([JEP 454](https://openjdk.org/jeps/454)) released in JDK 22. The combination of libvips and FFM makes for performant, safe, and ergonomic image
manipulation in JVM systems, supporting a vast range of image formats, including HEIC, JXL, WebP, PNG, JPEG, and more.
Pronounced "vips (like zips) eff-eff-emm".
([JEP 454](https://openjdk.org/jeps/454)), and the "Class-File API" ([JEP 457](https://openjdk.org/jeps/457)) released in JDK 22. The combination
of libvips, FFM, and auto-generated helpers makes for performant, safe, and ergonomic image manipulation in JVM systems.
Supports a vast range of image formats, including HEIC, JXL, WebP, PNG, JPEG, and more. Pronounced "vips (like zips)
eff-eff-emm".

Bindings are automatically generated using `jextract`, and enhanced with some helpful wrapper functions to make usage
more idiomatic.
Expand All @@ -18,7 +19,9 @@ Incubating in [Photo Fox](https://github.com/lopcode/photo-fox).
upstream changes can be rapidly integrated ✅
* Core module should only include this automated output, with a minimum of extra things that can break as upstreams
change ✅
* If helpers are required, publish in another artifact
* If helpers are required, publish in another artifact ✅
* Generate these too, if possible
* Keep generated APIs as similar to the original as possible
* Incubate in Photo Fox with some "real world" usage

## Samples
Expand All @@ -40,9 +43,12 @@ To get set up to run samples (on macOS):
[main] INFO vipsffm.VipsFfm - running sample "GetVersionSample"...
[main] INFO vipsffm.GetVersionSample - libvips version: "8.15.2"
[main] INFO vipsffm.VipsFfm - validation succeeded ✅
[main] INFO vipsffm.VipsFfm - running sample "CreateThumbnailSample"...
[main] INFO vipsffm.VipsFfm - running sample "RawCreateThumbnailSample"...
[main] INFO vipsffm.GetVersionSample - source image size: 2490 x 3084
[main] INFO vipsffm.GetVersionSample - output image size: 323 x 400
[main] INFO vipsffm.VipsFfm - validation succeeded ✅
[main] INFO vipsffm.VipsFfm - running sample "HelperCreateThumbnailSample"...
[main] INFO vipsffm.GetVersionSample - source image size: 2490 x 3084
[main] INFO vipsffm.VipsFfm - validation succeeded ✅
[main] INFO vipsffm.VipsFfm - all samples ran successfully 🎉
```
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public interface Function {
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.ofVoid(
vips_h.C_POINTER
VipsRaw.C_POINTER
);

/**
Expand All @@ -41,7 +41,7 @@ public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = vips_h.upcallHandle(GObjectFinalizeFunc.Function.class, "apply", $DESC);
private static final MethodHandle UP$MH = VipsRaw.upcallHandle(GObjectFinalizeFunc.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ public interface Function {
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.ofVoid(
vips_h.C_POINTER,
vips_h.C_INT,
vips_h.C_POINTER,
vips_h.C_POINTER
VipsRaw.C_POINTER,
VipsRaw.C_INT,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER
);

/**
Expand All @@ -44,7 +44,7 @@ public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = vips_h.upcallHandle(GObjectGetPropertyFunc.Function.class, "apply", $DESC);
private static final MethodHandle UP$MH = VipsRaw.upcallHandle(GObjectGetPropertyFunc.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ public interface Function {
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.ofVoid(
vips_h.C_POINTER,
vips_h.C_INT,
vips_h.C_POINTER,
vips_h.C_POINTER
VipsRaw.C_POINTER,
VipsRaw.C_INT,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER
);

/**
Expand All @@ -44,7 +44,7 @@ public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = vips_h.upcallHandle(GObjectSetPropertyFunc.Function.class, "apply", $DESC);
private static final MethodHandle UP$MH = VipsRaw.upcallHandle(GObjectSetPropertyFunc.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public interface Function {
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.of(
vips_h.C_INT,
vips_h.C_POINTER,
vips_h.C_POINTER
VipsRaw.C_INT,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER
);

/**
Expand All @@ -43,7 +43,7 @@ public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = vips_h.upcallHandle(GTypeClassCacheFunc.Function.class, "apply", $DESC);
private static final MethodHandle UP$MH = VipsRaw.upcallHandle(GTypeClassCacheFunc.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
Expand Down
26 changes: 26 additions & 0 deletions core/src/main/java/app/photofox/vipsffm/generated/GValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Generated by jextract

package app.photofox.vipsffm.generated;

import java.lang.invoke.*;
import java.lang.foreign.*;
import java.nio.ByteOrder;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

import static java.lang.foreign.ValueLayout.*;
import static java.lang.foreign.MemoryLayout.PathElement.*;

/**
* {@snippet lang=c :
* typedef struct _GValue GValue
* }
*/
public class GValue extends _GValue {

GValue() {
// Should not be called directly
}
}

26 changes: 26 additions & 0 deletions core/src/main/java/app/photofox/vipsffm/generated/GValueArray.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Generated by jextract

package app.photofox.vipsffm.generated;

import java.lang.invoke.*;
import java.lang.foreign.*;
import java.nio.ByteOrder;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

import static java.lang.foreign.ValueLayout.*;
import static java.lang.foreign.MemoryLayout.PathElement.*;

/**
* {@snippet lang=c :
* typedef struct _GValueArray GValueArray
* }
*/
public class GValueArray extends _GValueArray {

GValueArray() {
// Should not be called directly
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Generated by jextract

package app.photofox.vipsffm.generated;

import java.lang.invoke.*;
import java.lang.foreign.*;
import java.nio.ByteOrder;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

import static java.lang.foreign.ValueLayout.*;
import static java.lang.foreign.MemoryLayout.PathElement.*;

/**
* {@snippet lang=c :
* typedef void (*GValueTransform)(const GValue *, GValue *)
* }
*/
public class GValueTransform {

GValueTransform() {
// Should not be called directly
}

/**
* The function pointer signature, expressed as a functional interface
*/
public interface Function {
void apply(MemorySegment src_value, MemorySegment dest_value);
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.ofVoid(
VipsRaw.C_POINTER,
VipsRaw.C_POINTER
);

/**
* The descriptor of this function pointer
*/
public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = VipsRaw.upcallHandle(GValueTransform.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
* The lifetime of the returned segment is managed by {@code arena}
*/
public static MemorySegment allocate(GValueTransform.Function fi, Arena arena) {
return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, arena);
}

private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);

/**
* Invoke the upcall stub {@code funcPtr}, with given parameters
*/
public static void invoke(MemorySegment funcPtr,MemorySegment src_value, MemorySegment dest_value) {
try {
DOWN$MH.invokeExact(funcPtr, src_value, dest_value);
} catch (Throwable ex$) {
throw new AssertionError("should not reach here", ex$);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ public interface Function {
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.of(
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER
);

/**
Expand All @@ -46,7 +46,7 @@ public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = vips_h.upcallHandle(VipsArgumentClassMapFn.Function.class, "apply", $DESC);
private static final MethodHandle UP$MH = VipsRaw.upcallHandle(VipsArgumentClassMapFn.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ public interface Function {
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.of(
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER
);

/**
Expand All @@ -47,7 +47,7 @@ public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = vips_h.upcallHandle(VipsArgumentMapFn.Function.class, "apply", $DESC);
private static final MethodHandle UP$MH = VipsRaw.upcallHandle(VipsArgumentMapFn.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public class VipsBufferThread {
}

private static final GroupLayout $LAYOUT = MemoryLayout.structLayout(
vips_h.C_POINTER.withName("hash"),
vips_h.C_POINTER.withName("thread")
VipsRaw.C_POINTER.withName("hash"),
VipsRaw.C_POINTER.withName("thread")
).withName("$anon$81:9");

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public interface Function {
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.of(
vips_h.C_INT,
vips_h.C_POINTER,
vips_h.C_POINTER
VipsRaw.C_INT,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER
);

/**
Expand All @@ -43,7 +43,7 @@ public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = vips_h.upcallHandle(VipsCallbackFn.Function.class, "apply", $DESC);
private static final MethodHandle UP$MH = VipsRaw.upcallHandle(VipsCallbackFn.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public interface Function {
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.of(
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER
);

/**
Expand All @@ -43,7 +43,7 @@ public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = vips_h.upcallHandle(VipsClassMapFn.Function.class, "apply", $DESC);
private static final MethodHandle UP$MH = VipsRaw.upcallHandle(VipsClassMapFn.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ public interface Function {
}

private static final FunctionDescriptor $DESC = FunctionDescriptor.of(
vips_h.C_INT,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER,
vips_h.C_POINTER
VipsRaw.C_INT,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER,
VipsRaw.C_POINTER
);

/**
Expand All @@ -46,7 +46,7 @@ public static FunctionDescriptor descriptor() {
return $DESC;
}

private static final MethodHandle UP$MH = vips_h.upcallHandle(VipsGenerateFn.Function.class, "apply", $DESC);
private static final MethodHandle UP$MH = VipsRaw.upcallHandle(VipsGenerateFn.Function.class, "apply", $DESC);

/**
* Allocates a new upcall stub, whose implementation is defined by {@code fi}.
Expand Down
Loading

0 comments on commit b962f04

Please sign in to comment.