Skip to content

Commit df781b7

Browse files
authored
Image metadata getting and setting (#156)
* Add all vips_image_set functions to helper * Add metadata getter, setter, and fields methods on VImage * Allow fluent pattern for setting image metadata * Refactor to use vips_image_map for fields list * Add blob metadata support * Add image metadata support * Formatting fixup * Add link to libvips docs on VImage metadata functions * Refactor metadata getters to test for presence using image_get_typeof first
1 parent 9f88a3e commit df781b7

23 files changed

+10063
-5311
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ repositories {
2222
}
2323

2424
dependencies {
25-
implementation("app.photofox.vips-ffm:vips-ffm-core:1.6.0")
25+
implementation("app.photofox.vips-ffm:vips-ffm-core:1.7.0")
2626
}
2727
```
2828

core/src/main/java/app/photofox/vipsffm/VImage.java

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import app.photofox.vipsffm.enums.VipsSdfShape;
4242
import app.photofox.vipsffm.enums.VipsSize;
4343
import app.photofox.vipsffm.enums.VipsTextWrap;
44+
import app.photofox.vipsffm.jextract.VipsImageMapFn;
45+
import app.photofox.vipsffm.jextract.VipsRaw;
4446
import java.io.InputStream;
4547
import java.io.OutputStream;
4648
import java.lang.Double;
@@ -83,7 +85,9 @@ public boolean equals(Object o) {
8385
}
8486

8587
/// Gets the raw [MemorySegment] (C pointer) for this VipsImage struct
88+
///
8689
/// The memory address' lifetime is bound to the scope of the [#arena]
90+
///
8791
/// Usage of the memory address is strongly discouraged, but it is available if some functionality is missing and you need to use it with [VipsHelper]
8892
public MemorySegment getUnsafeStructAddress() {
8993
return this.address;
@@ -9756,4 +9760,165 @@ public static VImage newImage(Arena arena) throws VipsError {
97569760
var newImagePointer = VipsHelper.image_new(arena);
97579761
return new VImage(arena, newImagePointer);
97589762
}
9763+
9764+
/// Helper function to get the metadata stored at `name` on this image, of type `string`, or `null`
9765+
/// if not present
9766+
///
9767+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9768+
public String getString(String name) {
9769+
var type = VipsHelper.image_get_typeof(arena, this.address, name);
9770+
if (type == 0) {
9771+
return null;
9772+
}
9773+
var outPointer = arena.allocate(VipsRaw.C_POINTER);
9774+
var result = VipsHelper.image_get_string(arena, this.address, name, outPointer);
9775+
if (!VipsValidation.isValidResult(result)) {
9776+
VipsValidation.throwVipsError("image_get_string");
9777+
}
9778+
if (!VipsValidation.isValidPointer(outPointer)) {
9779+
throw new VipsError("failed to read value of type string from field: " + name);
9780+
}
9781+
var dereferenced = outPointer.get(VipsRaw.C_POINTER, 0);
9782+
return dereferenced.getString(0);
9783+
}
9784+
9785+
/// Helper function to set the metadata stored at `name` on this image, of type `string`
9786+
///
9787+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9788+
public VImage set(String name, String value) {
9789+
VipsHelper.image_set_string(arena, this.address, name, value);
9790+
return this;
9791+
}
9792+
9793+
/// Helper function to get the metadata stored at `name` on this image, of type `int`, or `null`
9794+
/// if not present
9795+
///
9796+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9797+
public Integer getInt(String name) {
9798+
var type = VipsHelper.image_get_typeof(arena, this.address, name);
9799+
if (type == 0) {
9800+
return null;
9801+
}
9802+
var outPointer = arena.allocate(VipsRaw.C_POINTER);
9803+
var result = VipsHelper.image_get_int(arena, this.address, name, outPointer);
9804+
if (!VipsValidation.isValidResult(result)) {
9805+
VipsValidation.throwVipsError("image_get_int");
9806+
}
9807+
if (!VipsValidation.isValidPointer(outPointer)) {
9808+
throw new VipsError("failed to read value of type int from field: " + name);
9809+
}
9810+
return outPointer.get(VipsRaw.C_INT, 0);
9811+
}
9812+
9813+
/// Helper function to set the metadata stored at `name` on this image, of type `int`
9814+
///
9815+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9816+
public VImage set(String name, Integer value) {
9817+
VipsHelper.image_set_int(arena, this.address, name, value);
9818+
return this;
9819+
}
9820+
9821+
/// Helper function to get the metadata stored at `name` on this image, of type `double`, or `null`
9822+
/// if not present
9823+
///
9824+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9825+
public Double getDouble(String name) {
9826+
var type = VipsHelper.image_get_typeof(arena, this.address, name);
9827+
if (type == 0) {
9828+
return null;
9829+
}
9830+
var outPointer = arena.allocate(VipsRaw.C_POINTER);
9831+
var result = VipsHelper.image_get_double(arena, this.address, name, outPointer);
9832+
if (!VipsValidation.isValidResult(result)) {
9833+
VipsValidation.throwVipsError("image_get_double");
9834+
}
9835+
if (!VipsValidation.isValidPointer(outPointer)) {
9836+
throw new VipsError("failed to read value of type double from field: " + name);
9837+
}
9838+
return outPointer.get(VipsRaw.C_DOUBLE, 0);
9839+
}
9840+
9841+
/// Helper function to set the metadata stored at `name` on this image, of type `double`
9842+
///
9843+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9844+
public VImage set(String name, Double value) {
9845+
VipsHelper.image_set_double(arena, this.address, name, value);
9846+
return this;
9847+
}
9848+
9849+
/// Helper function to get the metadata stored at `name` on this image, of type `blob`, or `null`
9850+
/// if not present
9851+
///
9852+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9853+
public VBlob getBlob(String name) {
9854+
var type = VipsHelper.image_get_typeof(arena, this.address, name);
9855+
if (type == 0) {
9856+
return null;
9857+
}
9858+
var outPointer = arena.allocate(VipsRaw.C_POINTER);
9859+
var outLengthPointer = arena.allocate(VipsRaw.C_LONG);
9860+
var result = VipsHelper.image_get_blob(arena, this.address, name, outPointer, outLengthPointer);
9861+
if (!VipsValidation.isValidResult(result)) {
9862+
VipsValidation.throwVipsError("image_get_blob");
9863+
}
9864+
if (!VipsValidation.isValidPointer(outPointer)) {
9865+
throw new VipsError("failed to read value of type blob from field: " + name);
9866+
}
9867+
var blobAddress = outPointer.get(VipsRaw.C_POINTER, 0);
9868+
return new VBlob(arena, blobAddress);
9869+
}
9870+
9871+
/// Helper function to set the metadata stored at `name` on this image, of type `blob`
9872+
///
9873+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9874+
public VImage set(String name, VBlob value) {
9875+
VipsHelper.image_set_blob(arena, this.address, name, MemorySegment.NULL, value.address, value.byteSize());
9876+
return this;
9877+
}
9878+
9879+
/// Helper function to get the metadata stored at `name` on this image, of type `image`, or `null`
9880+
/// if not present
9881+
///
9882+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9883+
public VImage getImage(String name) {
9884+
var type = VipsHelper.image_get_typeof(arena, this.address, name);
9885+
if (type == 0) {
9886+
return null;
9887+
}
9888+
var outPointer = arena.allocate(VipsRaw.C_POINTER);
9889+
var result = VipsHelper.image_get_image(arena, this.address, name, outPointer);
9890+
if (!VipsValidation.isValidResult(result)) {
9891+
VipsValidation.throwVipsError("image_get_image");
9892+
}
9893+
if (!VipsValidation.isValidPointer(outPointer)) {
9894+
throw new VipsError("failed to read value of type image from field: " + name);
9895+
}
9896+
var imageAddress = outPointer.get(VipsRaw.C_POINTER, 0).reinterpret(arena, VipsRaw::g_object_unref);
9897+
return new VImage(arena, imageAddress);
9898+
}
9899+
9900+
/// Helper function to set the metadata stored at `name` on this image, of type `image`
9901+
///
9902+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9903+
public VImage set(String name, VImage value) {
9904+
VipsHelper.image_set_image(arena, this.address, name, value.address);
9905+
return this;
9906+
}
9907+
9908+
/// Returns a list of all metadata entry names for this image
9909+
///
9910+
/// See also: [libvips header docs](https://www.libvips.org/API/current/libvips-header.html)
9911+
public List<String> getFields() {
9912+
var fieldNameStrings = new ArrayList<String>();
9913+
VipsImageMapFn.Function fn = (_, name, _, _) -> {
9914+
if (!VipsValidation.isValidPointer(name)) {
9915+
return MemorySegment.NULL;
9916+
}
9917+
fieldNameStrings.add(name.getString(0));
9918+
return MemorySegment.NULL;
9919+
};
9920+
var callbackPointer = VipsImageMapFn.allocate(fn, arena);
9921+
VipsRaw.vips_image_map(this.address, callbackPointer, MemorySegment.NULL);
9922+
return fieldNameStrings;
9923+
}
97599924
}

0 commit comments

Comments
 (0)