-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathjaypeg.c
99 lines (76 loc) · 2.92 KB
/
jaypeg.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "erl_nif.h"
#include <jpeglib.h>
ERL_NIF_TERM decode_properties(ErlNifEnv *env, int width, int height,
int channels) {
ERL_NIF_TERM width_term;
width_term = enif_make_tuple2(env, enif_make_atom(env, "width"),
enif_make_int(env, width));
ERL_NIF_TERM height_term;
height_term = enif_make_tuple2(env, enif_make_atom(env, "height"),
enif_make_int(env, height));
ERL_NIF_TERM channels_term;
channels_term = enif_make_tuple2(env, enif_make_atom(env, "channels"),
enif_make_int(env, channels));
ERL_NIF_TERM items[3] = {width_term, height_term, channels_term};
return enif_make_list_from_array(
env, items, sizeof(items) / sizeof(ERL_NIF_TERM));
}
static ERL_NIF_TERM decode(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ERL_NIF_TERM jpeg_binary_term;
jpeg_binary_term = argv[0];
if (!enif_is_binary(env, jpeg_binary_term)) {
return enif_make_badarg(env);
}
ErlNifBinary jpeg_binary;
enif_inspect_binary(env, jpeg_binary_term, &jpeg_binary);
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
FILE * img_src = fmemopen(jpeg_binary.data, jpeg_binary.size, "rb");
if (img_src == NULL)
return enif_make_tuple2(env, enif_make_atom(env, "error"),
enif_make_atom(env, "fmemopen"));
jpeg_stdio_src(&cinfo, img_src);
int error_check;
error_check = jpeg_read_header(&cinfo, TRUE);
if (error_check != 1)
return enif_make_tuple2(env, enif_make_atom(env, "error"),
enif_make_atom(env, "bad_jpeg"));
jpeg_start_decompress(&cinfo);
int width, height, num_pixels, row_stride;
width = cinfo.output_width;
height = cinfo.output_height;
num_pixels = cinfo.output_components;
unsigned long output_size;
output_size = width * height * num_pixels;
row_stride = width * num_pixels;
ErlNifBinary bmp_binary;
enif_alloc_binary(output_size, &bmp_binary);
while (cinfo.output_scanline < cinfo.output_height) {
unsigned char *buf[1];
buf[0] = bmp_binary.data + cinfo.output_scanline * row_stride;
jpeg_read_scanlines(&cinfo, buf, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(img_src);
ERL_NIF_TERM bmp_term;
bmp_term = enif_make_binary(env, &bmp_binary);
ERL_NIF_TERM properties_term;
properties_term = decode_properties(env, width, height, num_pixels);
return enif_make_tuple3(
env, enif_make_atom(env, "ok"), bmp_term, properties_term);
}
static int upgrade(ErlNifEnv* env, void** priv, void** old_priv, ERL_NIF_TERM load_info)
{
return 0;
}
static ErlNifFunc nif_funcs[] = {
{"decode", 1, decode}
};
ERL_NIF_INIT(Elixir.Jaypeg, nif_funcs, NULL, NULL, &upgrade, NULL)
/* Local Variables: */
/* c-basic-offset: 2 */
/* End: */