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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
Erlang Image Manipulation Process
=================================
`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_opts()) ->
{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.
**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()}.
```
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.
**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 |
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.
|