Skip to content

Commit

Permalink
Merge pull request #17 from akash-akya/vips-blob
Browse files Browse the repository at this point in the history
Add support for VipsBlob & VipsRefString
  • Loading branch information
akash-akya authored Sep 18, 2021
2 parents 37a5b39 + b90e7bf commit dae00d4
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 103 deletions.
166 changes: 166 additions & 0 deletions c_src/vips_boxed.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,77 @@ ERL_NIF_TERM nif_image_array(ErlNifEnv *env, int argc,
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);
Expand Down Expand Up @@ -348,3 +419,98 @@ ERL_NIF_TERM nif_vips_image_array_to_erl_list(ErlNifEnv *env, int argc,
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);
}
11 changes: 11 additions & 0 deletions c_src/vips_boxed.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ ERL_NIF_TERM nif_double_array(ErlNifEnv *env, int argc,
ERL_NIF_TERM nif_image_array(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

ERL_NIF_TERM nif_vips_blob(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);

ERL_NIF_TERM nif_vips_ref_string(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

ERL_NIF_TERM nif_vips_int_array_to_erl_list(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

Expand All @@ -20,4 +25,10 @@ ERL_NIF_TERM nif_vips_double_array_to_erl_list(ErlNifEnv *env, int argc,
ERL_NIF_TERM nif_vips_image_array_to_erl_list(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

ERL_NIF_TERM nif_vips_blob_to_erl_binary(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

ERL_NIF_TERM nif_vips_ref_string_to_erl_binary(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

#endif
34 changes: 3 additions & 31 deletions c_src/vips_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,6 @@ static ERL_NIF_TERM vips_image_header_read_error(ErlNifEnv *env,
return make_error(env, "Failed to read image metadata");
}

static int get_ref_string(ErlNifEnv *env, VipsImage *image, const char *name,
ERL_NIF_TERM *value) {
const char *str;
unsigned char *temp;
ssize_t length;

if (vips_image_get_string(image, name, &str)) {
error("Failed to get string. error: %s", vips_error_buffer());
vips_error_clear();
*value = make_error(env, "Failed to get string");
return -1;
}

length = strlen(str);
temp = enif_make_new_binary(env, length, value);
memcpy(temp, str, length);

return 0;
}

ERL_NIF_TERM nif_image_new_from_file(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);
Expand Down Expand Up @@ -428,7 +408,7 @@ ERL_NIF_TERM nif_image_get_header(ErlNifEnv *env, int argc,
char header_name[MAX_HEADER_NAME_LENGTH];
GType type;
ERL_NIF_TERM ret;
ERL_NIF_TERM value;
ERL_NIF_TERM type_name;
ErlNifTime start;
GValue gvalue = {0};
VixResult res;
Expand Down Expand Up @@ -463,16 +443,8 @@ ERL_NIF_TERM nif_image_get_header(ErlNifEnv *env, int argc,
res = g_value_to_erl_term(env, gvalue);

if (res.is_success) {

if (type == VIPS_TYPE_REF_STRING) {
if (get_ref_string(env, image, header_name, &value))
ret = enif_make_tuple2(env, ATOM_ERROR, value);
else
ret = make_ok(env, value);
} else {
ret = make_ok(env, res.result);
}

type_name = make_binary(env, g_type_name(type));
ret = make_ok(env, enif_make_tuple2(env, type_name, res.result));
} else {
ret = enif_make_tuple2(env, ATOM_ERROR, res.result);
}
Expand Down
5 changes: 5 additions & 0 deletions c_src/vix.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,15 @@ static ErlNifFunc nif_funcs[] = {
{"nif_int_array", 1, nif_int_array, 0},
{"nif_image_array", 1, nif_image_array, 0},
{"nif_double_array", 1, nif_double_array, 0},
{"nif_vips_blob", 1, nif_vips_blob, 0},
{"nif_vips_ref_string", 1, nif_vips_ref_string, 0},
{"nif_vips_int_array_to_erl_list", 1, nif_vips_int_array_to_erl_list, 0},
{"nif_vips_double_array_to_erl_list", 1, nif_vips_double_array_to_erl_list,
0},
{"nif_vips_image_array_to_erl_list", 1, nif_vips_image_array_to_erl_list,
0},
{"nif_vips_blob_to_erl_binary", 1, nif_vips_blob_to_erl_binary, 0},
{"nif_vips_ref_string_to_erl_binary", 1, nif_vips_ref_string_to_erl_binary,
0}};

ERL_NIF_INIT(Elixir.Vix.Nif, nif_funcs, &on_load, NULL, NULL, NULL)
7 changes: 7 additions & 0 deletions lib/vix/g_object/g_param_spec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,11 @@ defmodule Vix.GObject.GParamSpec do
@type t :: %{}

defstruct [:param_name, :desc, :spec_type, :value_type, :data, :priority, :flags]

def type(%__MODULE__{spec_type: "GParamEnum", value_type: value_type}), do: {:enum, value_type}

def type(%__MODULE__{spec_type: "GParamFlags", value_type: value_type}),
do: {:flags, value_type}

def type(%__MODULE__{value_type: value_type}), do: value_type
end
12 changes: 12 additions & 0 deletions lib/vix/nif.ex
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ defmodule Vix.Nif do
def nif_double_array(_double_list),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_vips_blob(_binary),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_vips_ref_string(_binary),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_vips_int_array_to_erl_list(_vips_int_array),
do: :erlang.nif_error(:nif_library_not_loaded)

Expand All @@ -116,4 +122,10 @@ defmodule Vix.Nif do

def nif_vips_image_array_to_erl_list(_vips_image_array),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_vips_blob_to_erl_binary(_vips_blob),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_vips_ref_string_to_erl_binary(_vips_blob),
do: :erlang.nif_error(:nif_library_not_loaded)
end
Loading

0 comments on commit dae00d4

Please sign in to comment.