1
1
package app .photofox .vipsffm ;
2
2
3
- import app .photofox .vipsffm .jextract .GValue ;
4
- import app .photofox .vipsffm .jextract .VipsRaw ;
3
+ import app .photofox .vipsffm .jextract .*;
5
4
6
5
import java .lang .foreign .Arena ;
7
6
import java .lang .foreign .MemoryLayout ;
@@ -30,27 +29,37 @@ public static void invokeOperation(
30
29
List <? extends VipsOption > args
31
30
) throws VipsError {
32
31
// https://www.libvips.org/API/current/binding.html
33
- var rawOperation = VipsRaw .vips_operation_new (arena .allocateFrom (nickname ));
34
- if (!VipsValidation .isValidPointer (rawOperation )) {
32
+ var operation = VipsRaw .vips_operation_new (arena .allocateFrom (nickname ));
33
+ if (!VipsValidation .isValidPointer (operation )) {
35
34
VipsValidation .throwVipsError (String .format ("failed to create operation for %s" , nickname ));
36
35
}
37
- final var operation = rawOperation . reinterpret ( arena , VipsRaw :: g_object_unref );
36
+
38
37
if (stringOptions != null && !stringOptions .isBlank ()) {
39
- VipsHelper .object_set_from_string (arena , operation , stringOptions );
38
+ var result = VipsHelper .object_set_from_string (arena , operation , stringOptions );
39
+ if (!VipsValidation .isValidResult (result )) {
40
+ VipsHelper .object_unref_outputs (operation );
41
+ VipsRaw .g_object_unref (operation );
42
+ VipsValidation .throwVipsError (String .format ("failed to create cached operation for %s" , nickname ));
43
+ }
40
44
}
41
45
42
46
setInputOptions (arena , args , operation );
43
47
44
- var operationResult = VipsRaw .vips_cache_operation_build (operation );
45
- if (!VipsValidation .isValidPointer (operationResult )) {
48
+ var cachedOperation = VipsRaw .vips_cache_operation_build (operation );
49
+ if (!VipsValidation .isValidPointer (cachedOperation )) {
50
+ VipsHelper .object_unref_outputs (operation );
51
+ VipsRaw .g_object_unref (operation );
46
52
VipsValidation .throwVipsError (String .format ("failed to create cached operation for %s" , nickname ));
47
53
}
48
- operationResult .reinterpret (arena , (it ) -> {
49
- VipsHelper .object_unref_outputs (it );
50
- VipsRaw .g_object_unref (it );
51
- });
54
+ VipsRaw .g_object_unref (operation );
55
+ operation = cachedOperation ;
52
56
53
- readOutputOptions (arena , args , operationResult );
57
+ try {
58
+ readOutputOptions (arena , args , operation );
59
+ } finally {
60
+ VipsHelper .object_unref_outputs (operation );
61
+ VipsRaw .g_object_unref (operation );
62
+ }
54
63
}
55
64
56
65
private static void readOutputOptions (
@@ -66,7 +75,21 @@ private static void readOutputOptions(
66
75
private static void readOutputOption (Arena arena , MemorySegment operation , VipsOption option ) {
67
76
var optionKey = option .key ();
68
77
var keyCString = arena .allocateFrom (optionKey );
69
- var gvaluePointer = GValue .allocate (arena ).reinterpret (arena , VipsRaw ::g_value_unset );
78
+ var gvaluePointer = GValue .allocate (arena );
79
+ try {
80
+ readGValueAndSetOptionValue (arena , operation , option , gvaluePointer , keyCString );
81
+ } finally {
82
+ VipsRaw .g_value_unset (gvaluePointer );
83
+ }
84
+ }
85
+
86
+ private static void readGValueAndSetOptionValue (
87
+ Arena arena ,
88
+ MemorySegment operation ,
89
+ VipsOption option ,
90
+ MemorySegment gvaluePointer ,
91
+ MemorySegment keyCString
92
+ ) {
70
93
switch (option ) {
71
94
case VipsOption .Int o -> {
72
95
VipsRaw .g_value_init (gvaluePointer , G_TYPE_INT ());
@@ -210,7 +233,20 @@ private static void setInputOption(
210
233
) {
211
234
var optionKey = option .key ();
212
235
var keyCString = arena .allocateFrom (optionKey );
213
- var gvaluePointer = GValue .allocate (arena ).reinterpret (arena , VipsRaw ::g_value_unset );
236
+ var gvaluePointer = GValue .allocate (arena );
237
+ try {
238
+ setGValueFromOption (arena , option , gvaluePointer );
239
+ VipsRaw .g_object_set_property (operation , keyCString , gvaluePointer );
240
+ } finally {
241
+ VipsRaw .g_value_unset (gvaluePointer );
242
+ }
243
+ }
244
+
245
+ private static void setGValueFromOption (
246
+ Arena arena ,
247
+ VipsOption option ,
248
+ MemorySegment gvaluePointer
249
+ ) {
214
250
switch (option ) {
215
251
case VipsOption .Int o -> {
216
252
var value = o .valueOrThrow ();
@@ -281,14 +317,15 @@ private static void setInputOption(
281
317
var value = o .valueOrThrow ();
282
318
var valueSize = value .size ();
283
319
VipsRaw .g_value_init (gvaluePointer , vips_array_image_get_type ());
284
- var arrayPointer = arena .allocate (C_POINTER , valueSize );
320
+ VipsRaw .vips_value_set_array_image (gvaluePointer , valueSize );
321
+ var vipsArrayPointer = VipsRaw .vips_value_get_array_image (gvaluePointer , MemorySegment .NULL );
285
322
for (int i = 0 ; i < valueSize ; i ++) {
286
323
var imageAddress = value .get (i ).address ;
287
- arrayPointer .setAtIndex (C_POINTER , i , imageAddress );
324
+ // we must ref inputs to vips_array_image_get_type
325
+ // it should not be unreffed here - it will get unreffed above
326
+ VipsRaw .g_object_ref (imageAddress );
327
+ vipsArrayPointer .setAtIndex (C_POINTER , i , imageAddress );
288
328
}
289
- VipsRaw .vips_value_set_array_image (gvaluePointer , valueSize );
290
- var vipsArrayPointer = VipsRaw .vips_value_get_array_image (gvaluePointer , MemorySegment .NULL );
291
- vipsArrayPointer .set (C_POINTER , 0 , arrayPointer );
292
329
}
293
330
case VipsOption .Interpolate o -> {
294
331
var value = o .valueOrThrow ();
@@ -301,7 +338,6 @@ private static void setInputOption(
301
338
VipsRaw .g_value_set_int (gvaluePointer , value .getRawValue ());
302
339
}
303
340
}
304
- VipsRaw .g_object_set_property (operation , keyCString , gvaluePointer );
305
341
}
306
342
307
343
public static MemorySegment makeCharStarArray (Arena arena , List <String > strings ) {
0 commit comments