Current section
Files
Jump to
Current section
Files
c_src/vice_facedetect.c
#include <stdio.h>
#include <string.h>
#include "facedetect.h"
#include "erl_nif.h"
ERL_NIF_TERM mk_atom(ErlNifEnv* env, const char* atom) {
ERL_NIF_TERM ret;
if(!enif_make_existing_atom(env, atom, &ret, ERL_NIF_LATIN1)) {
return enif_make_atom(env, atom);
}
return ret;
}
ERL_NIF_TERM mk_error(ErlNifEnv* env, const char* mesg) {
return enif_make_tuple2(env, mk_atom(env, "error"), mk_atom(env, mesg));
}
char * bin2str(ErlNifBinary bin) {
char *str = (char*)malloc(sizeof(char)*(bin.size + 1));
memset(str, 0, bin.size + 1);
strncpy(str, bin.data, bin.size);
return str;
}
ERL_NIF_TERM maps_put(
ErlNifEnv* env,
ERL_NIF_TERM map,
char *key,
int value) {
ERL_NIF_TERM out = enif_make_new_map(env);
enif_make_map_put(env, map, mk_atom(env, key), enif_make_int(env, value), &out);
return out;
}
ERL_NIF_TERM mk_eyes(ErlNifEnv *env, int x, int y, int width, int height) {
return enif_make_list4(
env,
enif_make_tuple2(
env,
mk_atom(env, "x"),
enif_make_int(env, x)),
enif_make_tuple2(
env,
mk_atom(env, "y"),
enif_make_int(env, y)),
enif_make_tuple2(
env,
mk_atom(env, "width"),
enif_make_int(env, width)),
enif_make_tuple2(
env,
mk_atom(env, "height"),
enif_make_int(env, height)));
}
ERL_NIF_TERM mk_face(ErlNifEnv *env, int x, int y, int width, int height, const ERL_NIF_TERM eyes[], unsigned nb_eyes) {
return enif_make_list5(
env,
enif_make_tuple2(
env,
mk_atom(env, "x"),
enif_make_int(env, x)),
enif_make_tuple2(
env,
mk_atom(env, "y"),
enif_make_int(env, y)),
enif_make_tuple2(
env,
mk_atom(env, "width"),
enif_make_int(env, width)),
enif_make_tuple2(
env,
mk_atom(env, "height"),
enif_make_int(env, height)),
enif_make_tuple2(
env,
mk_atom(env, "eyes"),
enif_make_list_from_array(env, eyes, nb_eyes))
);
}
static ERL_NIF_TERM faces(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
int rcod;
s_detect faces;
ErlNifBinary img;
ErlNifBinary face_xml;
ErlNifBinary eyes_xml;
char *cimg;
char *cface_xml;
char *ceyes_xml;
size_t i, j;
ERL_NIF_TERM result;
if(argc != 3
|| !enif_inspect_binary(env, argv[0], &img)
|| !enif_inspect_binary(env, argv[1], &face_xml)
|| !enif_inspect_binary(env, argv[2], &eyes_xml)) {
return enif_make_badarg(env);
}
cimg = bin2str(img);
cface_xml = bin2str(face_xml);
ceyes_xml = bin2str(eyes_xml);
rcod = detect(cimg, cface_xml, ceyes_xml, &faces);
if(rcod == OK) {
ERL_NIF_TERM *erl_faces = (ERL_NIF_TERM*)malloc(sizeof(ERL_NIF_TERM)*faces.nb_faces);
for(i = 0; i < faces.nb_faces; i++) {
ERL_NIF_TERM *erl_eyes = NULL;
if(faces.faces[i].nb_eyes > 0) {
erl_eyes = (ERL_NIF_TERM*)malloc(sizeof(ERL_NIF_TERM)*faces.faces[i].nb_eyes);
for(j = 0; j < faces.faces[i].nb_eyes; j++) {
erl_eyes[j] = mk_eyes(env,
faces.faces[i].eyes[j].x,
faces.faces[i].eyes[j].y,
faces.faces[i].eyes[j].width,
faces.faces[i].eyes[j].height);
}
}
erl_faces[i] = mk_face(env,
faces.faces[i].x,
faces.faces[i].y,
faces.faces[i].width,
faces.faces[i].height,
erl_eyes,
faces.faces[i].nb_eyes);
}
result = enif_make_tuple2(
env,
mk_atom(env, "ok"),
enif_make_list_from_array(env, erl_faces, faces.nb_faces));
} else if(rcod == EMPTY_IMAGE) {
result = mk_error(env, "invalid_image");
} else if(rcod == NO_FACE) {
result = mk_error(env, "no_face_found");
} else {
result = mk_error(env, "detect_error");
}
free(cimg);
free(cface_xml);
free(ceyes_xml);
free_detect(faces);
return result;
}
static ErlNifFunc nif_funcs[] = {
{"faces", 3, faces}
};
ERL_NIF_INIT(vice_facedetect, nif_funcs, NULL, NULL, NULL, NULL);