eimp
is an Erlang/Elixir application for manipulating graphic images using
external C libraries. It supports WebP, JPEG, PNG and GIF.
NOTE: It's hard to say which versions of the C libraries are required, but it seems like not too old versions should work well.
$ ./configure
$ make
Note that running the configure script is highly recommended, so you should consider adding it in pre-hooks of your rebar configuration.
If no C libraries are found at compile time, the package will still be compiled. In this case the only usable function would be get_type/1.
The C code is compiled into external native binary called eimp
, which is
connected to Erlang VM using an external port. This is done because used C libraries
are known not to be extremely stable, thus, if you wrap them into the emulator
using a driver or NIF, they can crash the whole emulator.
When being loaded, the application starts a single eimp
process per CPU core
and uses a round-robin pool to schedule tasks to them. Simple recovery mechanisms
are also supported:
eimp
process has failed, next eimp
process in the pool is picked,
until the pool is exhaustedeimp
process is dead, it will be restarted automaticallyeimp
process is protected against decompression bombsBefore using the application you should start it with either eimp:start()
or
application:start(eimp)
.
Current API is simple and supports only a few functions:
-spec convert(In :: binary(), Format :: png|jpeg|webp|gif) -> {ok, Out :: binary()} |
{error, Reason :: error_reason()}.
Shorthand for convert(In, Format, [])
.
-spec convert(In :: binary(), Format :: png|jpeg|webp|gif,
Options :: [convert_opt() | limit_opt()]) ->
{ok, Out :: binary()} |
{error, Reason :: error_reason()}.
The function converts incoming data In
into format Format
. Note that you don't
have to pass the format of incoming data, becasue it will be detected automatically
using get_type/1
function. In the case of an error you can use Reason
to produce
a human-readable diagnostic text using format_error/1
.
The function also accepts a proplist of Options
. Currently available options are:
{scale, {Width, Height}}
: scales image to the new Width
and Height
.
No scaling is applied by default.{rate_limit, N}
: limit the number of calls to N
per minute, where
N > 0
. Must be used only in conjunction with limit_by
.{limit_by, Term}
: apply rate_limit
(see above) to the entity associtated
with Term
. The Term
may represent any value, such as an IP address, a username
and so on. The Term
must not be atom undefined
. For example a call to
convert(Data, Format, [{limit_by, {192,168,0,1}}, {rate_limit, 10}])
will fail with {error, too_man_requests}
if called more than 10 times within a minute.WARNING: the maximum resolution of an incoming image is hardcoded to be 25Mpx. This is a protection against decompression bombs.
-spec identify(Img :: binary()) -> {ok, Info :: info()} | {error, error_reason()}.
Shorthand for identify(Img, [])
.
-spec identify(Img :: binary(), LimitOptions :: [limit_opt()]) ->
{ok, Info :: info()} | {error, error_reason()}.
The function returns information about image Img
, where Info
is represented as:
[{type, Type :: img_type()},
{width, Width :: non_neg_integer()},
{height, Height :: non_neg_integer()}]
It is safe to assume that Info
always contains all these properties.
You can set limiting options in LimitOptions
, that is rate_limit
and limit_by
.
The meaning of the limiting options is the same as in convert/3
.
NOTE: If you only need to get a type of an image, you're better off using
get_type/1
function, because it doesn't involve interaction with eimp
process
and is, thus, much faster.
-spec format_error(Reason :: error_reason()) -> binary().
Creates diagnostic text from an error generated by convert/2
.
The Reason
can have the following values:
-type error_reason() :: unsupported_format |
timeout |
disconnected |
encode_failure |
decode_failure |
transform_failure |
too_many_requests |
image_too_big.
-spec get_type(Data :: binary()) -> png | jpeg | webp | gif | unknown.
Detects image format of Data
.
-spec is_supported(Format :: atom()) -> boolean.
Returns true
if Format
is known and compiled and false
otherwise.
-spec supported_formats() -> [png | jpeg | webp | gif].
Returns a list of all known and compiled formats.