Packages
vix
0.16.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.1
0.33.0
0.32.0
0.31.1
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.1
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.1
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.1
0.10.0
0.9.0
0.8.0
0.7.0
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.2.1
0.2.0
retired
0.1.0
NIF based bindings for libvips
Current section
Files
Jump to
Current section
Files
c_src/vips_boxed.c
#include "vips_boxed.h"
#include "g_object/g_boxed.h"
#include "g_object/g_object.h"
#include "utils.h"
#include <stdbool.h>
#include <vips/vips.h>
static VipsArrayInt *erl_list_to_vips_int_array(ErlNifEnv *env,
ERL_NIF_TERM list,
unsigned int length,
int *array) {
ERL_NIF_TERM head, tail;
int value;
tail = list;
for (unsigned int i = 0; i < length; i++) {
if (!enif_get_list_cell(env, tail, &head, &tail)) {
error("Failed to get list entry");
return NULL;
}
if (!enif_get_int(env, head, &value)) {
error("Failed to get int");
return NULL;
}
array[i] = value;
}
return vips_array_int_new(array, length);
}
static VipsArrayDouble *erl_list_to_vips_double_array(ErlNifEnv *env,
ERL_NIF_TERM list,
unsigned int length,
double *array) {
ERL_NIF_TERM head, tail;
double value;
tail = list;
for (unsigned int i = 0; i < length; i++) {
if (!enif_get_list_cell(env, tail, &head, &tail)) {
error("Failed to get list entry");
return NULL;
}
if (!enif_get_double(env, head, &value)) {
error("Failed to get double");
return NULL;
}
array[i] = value;
}
return vips_array_double_new(array, length);
}
static VipsArrayImage *erl_list_to_vips_image_array(ErlNifEnv *env,
ERL_NIF_TERM list,
unsigned int length,
VipsImage **array) {
ERL_NIF_TERM head, tail;
VipsImage *img;
tail = list;
for (unsigned int i = 0; i < length; i++) {
if (!enif_get_list_cell(env, tail, &head, &tail)) {
error("Failed to get list entry");
return NULL;
}
if (!erl_term_to_g_object(env, head, (GObject **)&img)) {
error("failed to get VipsImage");
return NULL;
}
array[i] = img;
}
return vips_array_image_new(array, length);
}
ERL_NIF_TERM nif_int_array(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
GBoxedResource *boxed_r;
unsigned int len;
int *array;
VipsArrayInt *vips_array;
ERL_NIF_TERM ret;
ErlNifTime start;
start = enif_monotonic_time(ERL_NIF_USEC);
if (!enif_get_list_length(env, argv[0], &len)) {
error("Failed to get list length");
ret = enif_make_badarg(env);
goto exit;
}
array = g_new(int, len);
boxed_r = enif_alloc_resource(G_BOXED_RT, sizeof(GBoxedResource));
vips_array = erl_list_to_vips_int_array(env, argv[0], len, array);
boxed_r->boxed_type = VIPS_TYPE_ARRAY_INT;
boxed_r->boxed_ptr = vips_array;
ret = enif_make_resource(env, boxed_r);
enif_release_resource(boxed_r);
g_free(array);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
return ret;
}
ERL_NIF_TERM nif_double_array(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
GBoxedResource *boxed_r;
unsigned int len;
double *array;
VipsArrayDouble *vips_array;
ERL_NIF_TERM ret;
ErlNifTime start;
start = enif_monotonic_time(ERL_NIF_USEC);
if (!enif_get_list_length(env, argv[0], &len)) {
error("Failed to get list length");
ret = enif_make_badarg(env);
goto exit;
}
array = g_new(double, len);
boxed_r = enif_alloc_resource(G_BOXED_RT, sizeof(GBoxedResource));
vips_array = erl_list_to_vips_double_array(env, argv[0], len, array);
boxed_r->boxed_type = VIPS_TYPE_ARRAY_DOUBLE;
boxed_r->boxed_ptr = vips_array;
ret = enif_make_resource(env, boxed_r);
enif_release_resource(boxed_r);
g_free(array);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
return ret;
}
ERL_NIF_TERM nif_image_array(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
GBoxedResource *boxed_r;
unsigned int len;
VipsImage **array;
VipsArrayImage *vips_array;
ERL_NIF_TERM ret;
ErlNifTime start;
start = enif_monotonic_time(ERL_NIF_USEC);
if (!enif_get_list_length(env, argv[0], &len)) {
error("Failed to get list length");
ret = enif_make_badarg(env);
goto exit;
}
array = g_new(VipsImage *, len);
boxed_r = enif_alloc_resource(G_BOXED_RT, sizeof(GBoxedResource));
vips_array = erl_list_to_vips_image_array(env, argv[0], len, array);
boxed_r->boxed_type = VIPS_TYPE_ARRAY_IMAGE;
boxed_r->boxed_ptr = vips_array;
ret = enif_make_resource(env, boxed_r);
enif_release_resource(boxed_r);
g_free(array);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
return ret;
}
ERL_NIF_TERM nif_vips_blob(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
GBoxedResource *boxed_r;
VipsBlob *vips_blob;
ERL_NIF_TERM ret;
ErlNifBinary bin;
ErlNifTime start;
start = enif_monotonic_time(ERL_NIF_USEC);
if (!enif_inspect_binary(env, argv[0], &bin)) {
error("failed to get binary from erl term");
ret = enif_make_badarg(env);
goto exit;
}
vips_blob = vips_blob_copy(bin.data, bin.size);
boxed_r = enif_alloc_resource(G_BOXED_RT, sizeof(GBoxedResource));
boxed_r->boxed_type = VIPS_TYPE_BLOB;
boxed_r->boxed_ptr = vips_blob;
ret = enif_make_resource(env, boxed_r);
enif_release_resource(boxed_r);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
return ret;
}
ERL_NIF_TERM nif_vips_ref_string(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
GBoxedResource *boxed_r;
VipsRefString *vips_ref_string;
ERL_NIF_TERM ret;
ErlNifBinary bin;
ErlNifTime start;
start = enif_monotonic_time(ERL_NIF_USEC);
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin)) {
error("failed to get binary from erl term");
ret = enif_make_badarg(env);
goto exit;
}
// we ensure that data is appended with NULL while passing string from elixir
vips_ref_string = vips_ref_string_new((const char *)bin.data);
if (!vips_ref_string) {
error("failed to create vips ref string");
ret = enif_make_badarg(env);
goto exit;
}
boxed_r = enif_alloc_resource(G_BOXED_RT, sizeof(GBoxedResource));
boxed_r->boxed_type = VIPS_TYPE_REF_STRING;
boxed_r->boxed_ptr = vips_ref_string;
ret = enif_make_resource(env, boxed_r);
enif_release_resource(boxed_r);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
return ret;
}
ERL_NIF_TERM nif_vips_int_array_to_erl_list(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
VipsArrayInt *int_array;
ERL_NIF_TERM list;
ERL_NIF_TERM vips_array_term;
GType type;
int *arr;
int n;
ErlNifTime start;
VixResult res;
start = enif_monotonic_time(ERL_NIF_USEC);
vips_array_term = argv[0];
if (!erl_term_boxed_type(env, vips_array_term, &type)) {
SET_ERROR_RESULT(env, "failed to get type of boxed term", res);
goto exit;
}
if (type != VIPS_TYPE_ARRAY_INT) {
SET_ERROR_RESULT(env, "term is not a VIPS_TYPE_ARRAY_INT", res);
goto exit;
}
if (!erl_term_to_g_boxed(env, vips_array_term, (gpointer *)&int_array)) {
SET_ERROR_RESULT(env, "failed to get boxed term", res);
goto exit;
}
arr = vips_array_int_get(int_array, &n);
list = enif_make_list(env, 0);
for (int i = n - 1; i >= 0; i--) {
list = enif_make_list_cell(env, enif_make_int(env, arr[i]), list);
}
SET_VIX_RESULT(res, list);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
if (res.is_success)
return make_ok(env, res.result);
else
return enif_make_tuple2(env, ATOM_ERROR, res.result);
}
ERL_NIF_TERM nif_vips_double_array_to_erl_list(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
VipsArrayDouble *double_array;
ERL_NIF_TERM list;
ERL_NIF_TERM vips_array_term;
GType type;
double *arr;
int n;
ErlNifTime start;
VixResult res;
start = enif_monotonic_time(ERL_NIF_USEC);
vips_array_term = argv[0];
if (!erl_term_boxed_type(env, vips_array_term, &type)) {
SET_ERROR_RESULT(env, "failed to get type of boxed term", res);
goto exit;
}
if (type != VIPS_TYPE_ARRAY_DOUBLE) {
SET_ERROR_RESULT(env, "term is not a VIPS_TYPE_ARRAY_DOUBLE", res);
goto exit;
}
if (!erl_term_to_g_boxed(env, vips_array_term, (gpointer *)&double_array)) {
SET_ERROR_RESULT(env, "failed to get boxed term", res);
goto exit;
}
arr = vips_array_double_get(double_array, &n);
list = enif_make_list(env, 0);
for (int i = n - 1; i >= 0; i--) {
list = enif_make_list_cell(env, enif_make_double(env, arr[i]), list);
}
SET_VIX_RESULT(res, list);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
if (res.is_success)
return make_ok(env, res.result);
else
return enif_make_tuple2(env, ATOM_ERROR, res.result);
}
ERL_NIF_TERM nif_vips_image_array_to_erl_list(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
VipsArrayImage *image_array;
ERL_NIF_TERM list;
ERL_NIF_TERM vips_array_term;
GType type;
VipsImage **arr;
VipsImage *image;
int n;
ErlNifTime start;
VixResult res;
start = enif_monotonic_time(ERL_NIF_USEC);
vips_array_term = argv[0];
if (!erl_term_boxed_type(env, vips_array_term, &type)) {
SET_ERROR_RESULT(env, "failed to get type of boxed term", res);
goto exit;
}
if (type != VIPS_TYPE_ARRAY_IMAGE) {
SET_ERROR_RESULT(env, "term is not a VIPS_TYPE_ARRAY_IMAGE", res);
goto exit;
}
if (!erl_term_to_g_boxed(env, vips_array_term, (gpointer *)&image_array)) {
SET_ERROR_RESULT(env, "failed to get boxed term", res);
goto exit;
}
arr = vips_array_image_get(image_array, &n);
list = enif_make_list(env, 0);
for (int i = n - 1; i >= 0; i--) {
image = arr[i];
g_object_ref(image);
list = enif_make_list_cell(env, g_object_to_erl_term(env, (GObject *)image),
list);
}
SET_VIX_RESULT(res, list);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
if (res.is_success)
return make_ok(env, res.result);
else
return enif_make_tuple2(env, ATOM_ERROR, res.result);
}
ERL_NIF_TERM nif_vips_blob_to_erl_binary(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
VipsBlob *blob;
ERL_NIF_TERM vips_blob_term;
ERL_NIF_TERM bin_term;
GType type;
size_t length;
const void *blob_data;
unsigned char *erl_bin_data;
ErlNifTime start;
VixResult res;
start = enif_monotonic_time(ERL_NIF_USEC);
vips_blob_term = argv[0];
if (!erl_term_boxed_type(env, vips_blob_term, &type)) {
SET_ERROR_RESULT(env, "failed to get type of boxed term", res);
goto exit;
}
if (type != VIPS_TYPE_BLOB) {
SET_ERROR_RESULT(env, "term is not a VIPS_TYPE_BLOB", res);
goto exit;
}
if (!erl_term_to_g_boxed(env, vips_blob_term, (gpointer *)&blob)) {
SET_ERROR_RESULT(env, "failed to get boxed term", res);
goto exit;
}
blob_data = vips_blob_get(blob, &length);
erl_bin_data = enif_make_new_binary(env, length, &bin_term);
memcpy(erl_bin_data, blob_data, length);
SET_VIX_RESULT(res, bin_term);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
if (res.is_success)
return make_ok(env, res.result);
else
return enif_make_tuple2(env, ATOM_ERROR, res.result);
}
ERL_NIF_TERM nif_vips_ref_string_to_erl_binary(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
VipsRefString *vips_ref_string;
ERL_NIF_TERM vips_ref_string_term;
ERL_NIF_TERM bin_term;
GType type;
size_t length;
const char *string;
unsigned char *erl_bin_data;
ErlNifTime start;
VixResult res;
start = enif_monotonic_time(ERL_NIF_USEC);
vips_ref_string_term = argv[0];
if (!erl_term_boxed_type(env, vips_ref_string_term, &type)) {
SET_ERROR_RESULT(env, "failed to get type of ref string term", res);
goto exit;
}
if (type != VIPS_TYPE_REF_STRING) {
SET_ERROR_RESULT(env, "term is not a VIPS_TYPE_REF_STRING", res);
goto exit;
}
if (!erl_term_to_g_boxed(env, vips_ref_string_term,
(gpointer *)&vips_ref_string)) {
SET_ERROR_RESULT(env, "failed to get boxed term", res);
goto exit;
}
string = vips_ref_string_get(vips_ref_string, &length);
erl_bin_data = enif_make_new_binary(env, length, &bin_term);
memcpy(erl_bin_data, string, length);
SET_VIX_RESULT(res, bin_term);
exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
if (res.is_success)
return make_ok(env, res.result);
else
return enif_make_tuple2(env, ATOM_ERROR, res.result);
}