https://github.com/processone/eimp
Erlang Image Manipulation Process
https://github.com/processone/eimp
erlang image-processing
Last synced: 17 days ago
JSON representation
Erlang Image Manipulation Process
- Host: GitHub
- URL: https://github.com/processone/eimp
- Owner: processone
- License: apache-2.0
- Created: 2017-09-11T06:34:44.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2025-03-27T14:47:50.000Z (about 1 month ago)
- Last Synced: 2025-04-13T04:59:50.701Z (17 days ago)
- Topics: erlang, image-processing
- Language: Erlang
- Size: 3.53 MB
- Stars: 48
- Watchers: 10
- Forks: 20
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
Erlang Image Manipulation Process
=================================[](https://github.com/processone/eimp/actions/workflows/ci.yml)
[](https://coveralls.io/github/processone/eimp?branch=master)
[](https://hex.pm/packages/eimp)`eimp` is an Erlang/Elixir application for manipulating graphic images using
external C libraries. It supports WebP, JPEG, PNG and GIF.# Requirements
- GNU Make
- GCC
- Erlang/OTP 17 and higher
- libgd
- libwebp
- libpng
- libjpeg**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.# Install
```
$ ./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](#get_type1).# Application design
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:
- if a request to `eimp` process has failed, next `eimp` process in the pool is picked,
until the pool is exhausted
- if an `eimp` process is dead, it will be restarted automatically
- an `eimp` process is protected against decompression bombs# Usage
Before using the application you should start it with either `eimp:start()` or
`application:start(eimp)`.# API
Current API is simple and supports only a few functions:
### convert/2
```erl
-spec convert(In :: binary(), Format :: png|jpeg|webp|gif) -> {ok, Out :: binary()} |
{error, Reason :: error_reason()}.
```Shorthand for `convert(In, Format, [])`.
### convert/3
```erl
-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, because 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.### identify/1
```erl
-spec identify(Img :: binary()) -> {ok, Info :: info()} | {error, error_reason()}.
```
Shorthand for `identify(Img, [])`.### identify/2
```erl
-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:
```erl
[{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.### format_error/1
```erl
-spec format_error(Reason :: error_reason()) -> binary().
```
Creates diagnostic text from an error generated by `convert/2`.
The `Reason` can have the following values:
```erl
-type error_reason() :: unsupported_format |
timeout |
disconnected |
encode_failure |
decode_failure |
transform_failure |
too_many_requests |
image_too_big.
```### get_type/1
```erl
-spec get_type(Data :: binary()) -> png | jpeg | webp | gif | unknown.
```
Detects image format of `Data`.### is_supported/1
```erl
-spec is_supported(Format :: atom()) -> boolean.
```
Returns `true` if `Format` is known and compiled and `false` otherwise.### supported_formats/0
```erl
-spec supported_formats() -> [png | jpeg | webp | gif].
```
Returns a list of all known and compiled formats.