Skip to content

Commit

Permalink
init version
Browse files Browse the repository at this point in the history
  • Loading branch information
velimir committed Jun 18, 2019
0 parents commit a569cc7
Show file tree
Hide file tree
Showing 12 changed files with 2,946 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
line_length: 80
]
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
jaypeg-*.tar

# Build artifacts
priv/jaypeg.so
priv/jaypeg.so.*
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CFLAGS = -g -O3 -Wall -std=c99
ERLANG_PATH = $(shell erl -eval 'io:format("~s", [lists:concat([code:root_dir(), "/erts-", erlang:system_info(version), "/include"])])' -s init stop -noshell)
CFLAGS += -I$(ERLANG_PATH)
CFLAGS += -Ic_src
CFLAGS += -g -DDEBUG -D_GNU_SOURCE
ifeq ($(shell uname -s), Darwin)
LDFLAGS += -flat_namespace -undefined suppress
endif
LIB_SO_NAME = priv/jaypeg.so
CFLAGS += -fPIC
NIF=c_src/jaypeg.c

$(LIB_SO_NAME): $(NIF)
mkdir -p priv
$(CC) $(CFLAGS) -shared $(LDFLAGS) $^ -ljpeg -o $@
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Jaypeg

**TODO: Add description**

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `jaypeg` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:jaypeg, "~> 0.1.0"}
]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/jaypeg](https://hexdocs.pm/jaypeg).

131 changes: 131 additions & 0 deletions c_src/jaypeg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#include "erl_nif.h"

#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.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 ERL_NIF_TERM resize(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ErlNifBinary in_img_binary;
enif_inspect_binary(env, argv[0], &in_img_binary);

unsigned in_width, in_height, num_channels;
enif_get_uint(env, argv[1], &in_width);
enif_get_uint(env, argv[2], &in_height);
enif_get_uint(env, argv[3], &num_channels);

unsigned out_width, out_height;
enif_get_uint(env, argv[4], &out_width);
enif_get_uint(env, argv[5], &out_height);

unsigned long output_size;
output_size = out_width * out_height * num_channels;
ErlNifBinary out_img_binary;
enif_alloc_binary(output_size, &out_img_binary);

if (stbir_resize_uint8(
in_img_binary.data, in_width, in_height, 0,
out_img_binary.data, out_width, out_height, 0, num_channels) != 1)
return enif_make_tuple2(
env,
enif_make_atom(env, "error"),
enif_make_atom(env, "resize"));

ERL_NIF_TERM out_img_term;
out_img_term = enif_make_binary(env, &out_img_binary);

return enif_make_tuple2(env, enif_make_atom(env, "ok"), out_img_term);
}

static ErlNifFunc nif_funcs[] = {
{"decode", 1, decode},
{"resize", 6, resize}
};

ERL_NIF_INIT(Elixir.Jaypeg, nif_funcs, NULL, NULL, NULL, NULL)

/* Local Variables: */
/* c-basic-offset: 2 */
/* End: */
Loading

0 comments on commit a569cc7

Please sign in to comment.