View Source Processing with custom functions
lib =
Regex.named_captures(~r/(?<lib>.+)documentation\/livebooks/, __DIR__)
|> Map.get("lib")
Mix.install([
# for local development
# {:waffle, path: lib}
:waffle
])
Definition
All starts from creating the definition and custom processing function
defmodule Avatar do
use Waffle.Definition
@versions [:original, :thumb]
def __storage, do: Waffle.Storage.Local
def filename(version, _), do: version
def transform(:thumb, _) do
&process/2
end
@spec process(
atom(),
Waffle.File.t()
) :: {:ok, Waffle.File.t()} | {:error, String.t()}
def process(_version, original_file) do
{:ok, file}
end
end
Then, you can store the file by calling Avatar.store/1
image = lib <> "test/support/image.png"
Avatar.store(image)
Understanding custom transformations
def process(_version, original_file) do
{:ok, file}
end
To generate a temporary path for the new file version
tmp_path = Waffle.File.generate_temporary_path(file)
or if the new version is going to have a new extension
tmp_path = Waffle.File.generate_temporary_path("png")
then, you can process your file and put the result into tmp_path.
To return the processed tmp file into the pipeline and clean it afterwards, create a new file struct
{:ok, %Waffle.File{file | path: tmp_path, is_tempfile?: true}}
You can combine it all together to use ExOptimizer
library
def process(_version, original_file) do
tmp_path = Waffle.File.generate_temporary_path(original_file)
File.cp!(original_file.path, tmp_path)
with {:ok, _} <- ExOptimizer.optimize(tmp_path) do
{
:ok,
%Waffle.File{original_file | path: tmp_path, is_tempfile?: true}
}
end
end
All together
We can create a bit more complex example, where we combine transformation done by external binary with transformation done by existing elixir library.
defmodule Avatar do
use Waffle.Definition
@versions [:original, :thumb]
def __storage, do: Waffle.Storage.Local
def filename(version, _), do: version
def transform(:thumb, _) do
&process/2
end
@spec process(
atom(),
Waffle.File.t()
) :: {:ok, Waffle.File.t()} | {:error, String.t()}
def process(_version, original_file) do
# convert .jpg to .png
args = "-strip -thumbnail 100x100^ -gravity center -extent 100x100 -format png"
with {:ok, file} <-
Waffle.Transformations.Convert.apply(
:convert,
original_file,
args,
:png
),
{:ok, _} <- ExOptimizer.optimize(file.path) do
{:ok, file}
end
end
end