defmodule Thumbp do
@moduledoc """
A Fastest WebP image thumbnail creator for Elixir.
"""
version = Mix.Project.config()[:version]
use RustlerPrecompiled,
otp_app: :thumbp,
crate: "thumbp",
base_url: "https://github.com/ryochin/thumbp/releases/download/v#{version}",
force_build: System.get_env("RUSTLER_PRECOMPILATION_EXAMPLE_BUILD") in ["1", "true"],
version: version
@type body :: binary
@type width :: pos_integer
@type height :: pos_integer
@type quality :: float | non_neg_integer
@type target_size :: pos_integer
@doc """
Create a thumbnail image
## Examples
iex> content = File.read!("./test/assets/images/sample.jpg")
iex> Thumbp.create(content, 320, 240)
{:ok, <<82, 73, 70, 70, 102, 12, 0, 0, 87, 69, 66, 80, ...>>}
"""
@spec create(body, width, height) :: {:ok, binary} | {:error, String.t()}
def create(body, width, height), do: create(body, width, height, nil, nil)
@doc """
Create a thumbnail image with options
# Quality
The quality ranges from 0 to 100, defaulting to 75.
# Target size
You can also specify a target size in bytes, although this will increase the processing time
by approximately 20% to 80%.
## Examples
iex> content = File.read!("./test/assets/images/sample.jpg")
iex> Thumbp.create(content, 320, 240, quality: 50)
iex> Thumbp.create(content, 320, 240, target_size: 12_000)
"""
@spec create(body, width, height, quality: quality) ::
{:ok, binary} | {:error, String.t()}
def create(body, width, height, quality: quality) when is_number(quality),
do: create(body, width, height, quality / 1, nil)
@spec create(body, width, height, target_size: target_size) ::
{:ok, binary} | {:error, String.t()}
def create(body, width, height, target_size: target_size)
when is_integer(target_size),
do: create(body, width, height, nil, target_size)
defp create(body, _, _, _, _) when is_nil(body), do: {:error, "body is empty"}
defp create(_, width, _, _, _) when width <= 0, do: {:error, "width must be > 0"}
defp create(_, _, height, _, _) when height <= 0, do: {:error, "height must be > 0"}
defp create(_, _, _, quality, _) when not is_nil(quality) and quality < 0,
do: {:error, "quality must be >= 0"}
defp create(_, _, _, quality, _) when not is_nil(quality) and quality > 100,
do: {:error, "quality must be <= 100"}
defp create(_, _, _, _, target_size) when not is_nil(target_size) and target_size <= 0,
do: {:error, "target_size must be > 0"}
@spec create(body, width, height, quality, target_size) ::
{:ok, binary} | {:error, String.t()}
defp create(body, width, height, quality, target_size) do
case _create(body, width, height, quality, target_size) do
binary when is_binary(binary) -> {:ok, binary}
error -> error
end
end
# NIF function definition
@spec _create(body, width, height, quality, target_size) ::
binary | {:error, String.t()}
defp _create(_body, _width, _height, _quality, _target_size),
do: :erlang.nif_error(:nif_not_loaded)
end