Packages
image
0.31.0
0.72.0
0.71.0
0.70.0
0.69.0
0.68.0
0.67.0
0.67.0-dev
retired
0.66.0
0.65.0
0.64.0
0.63.0
0.62.1
0.62.0
0.61.1
0.61.0
0.60.0
0.59.3
0.59.2
0.59.1
0.59.0
0.58.0
0.57.0
0.56.1
0.56.0
0.55.2
0.55.1
retired
0.55.0
0.54.4
0.54.3
0.54.2
0.54.1
0.54.0
0.53.0
0.52.3
0.52.2
0.52.1
0.52.0
retired
0.51.0
0.50.0
0.49.0
0.48.1
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.2
0.43.1
0.43.0
0.42.0
0.41.0
0.40.0
0.39.3
0.39.2
0.39.1
0.39.0
0.38.4
0.38.3
0.38.2
0.38.1
0.38.0
0.37.0
0.36.2
0.36.1
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.1
0.31.0
0.30.0
0.29.0
0.28.2
0.28.1
0.28.0
0.27.0
0.26.0
0.25.1
0.25.0
0.24.1
0.24.0
0.23.2
0.23.1
0.23.0
0.22.1
0.22.0
0.21.0
0.20.0
retired
0.19.0
0.18.1
0.18.0
0.17.0
0.16.0
0.15.0
0.14.4
0.14.2
0.14.1
0.14.0
retired
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.10.0-rc.0
retired
0.9.0
retired
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
An approachable image processing library primarily based upon Vix and libvips that is NIF-based, fast, multi-threaded, pipelined and has a low memory footprint.
Current section
Files
Jump to
Current section
Files
lib/image/options/compose.ex
defmodule Image.Options.Compose do
@moduledoc false
# This module provides functions to calculate
# x, y positions for compositions.
# Since x,y can be relative or absolution, can be symbolic
# or numeric and can even by a function this becomes more
# complex that it might initially seem
@typedoc """
Image compoositions options
"""
@type t :: [composition_option(), ...]
@typedoc """
When composing an image on a base image, these
options drive how the composition proceeds.
* `:x` describes the absolute `x` offset on the
base image where this image will be placed. If
this option is set to `:left`, `:center` or
`:right` then the `x` position will be calculated
relative to the base image. If `:x` is nil
(the default) then the image will be placed according
to the relative offset of the previously composed
image using `:dx`.
* `:y` describes the absolute `y` offset on the
base image where this image will be placed. If
this option is set to `:top`, `:middle` or
`:bottom` then the `y` position will be calculated
relative to the base image. If `:y` is nil
(the default) then the image will be placed according
to the relative offset of the previously composed
image using `:dy`.
* `:dx` describes the relative offset used to calculate
the `x` value. `:dx` is an integer offset from the
edge of the previously composed image. Which edge is
determined by the `:x_baseline` option. If `:x` is also
specified then `:x` is first calculated, then `:dx` is
added to it. In this case, `:x_baseline` is ignored.
* `:dy` describes the relative offset used to calculate
the `y` value. `:dy` is an integer offset from the
edge of the previously composed image. Which edge is
determined by the `:y_baseline` option. If `:y` is also
specified then `:y` is first calculated, then `:dy` is
added to it. In this case, `:x_baseline` is ignored.
* `:blend_mode` is the `t:Image.BlendMode.t/0` used when
composing this image over its base image. The default
is `:over` which is appropriate for most use cases.
* `:x_baseline` establishes the baseline on the
previously composed image from which `:dx` is
calculated. The default is `:right`.
* `:y_baseline` establishes the baseline on the
previously composed image from which `:dy` is
calculated. The default is `:bottom`.
"""
@type composition_option :: [
{:x, non_neg_integer() | nil | :left | :center | :right},
{:y, non_neg_integer() | nil | :top | :middle | :bottom},
{:dx, integer()},
{:dy, integer()},
{:blend_mode, Image.BlendMode.t()},
{:x_baseline, nil | :left | :center | :right},
{:y_baseline, nil | :top | :middle | :bottom}
]
@doc false
def get_x(image, prev_x, prev_width, x, dx, baseline) when is_function(x, 6) do
x = x.(image, prev_x, prev_width, x, dx, baseline)
get_x(image, prev_x, prev_width, x, dx, baseline)
end
def get_x(image, prev_x, prev_width, x, dx, baseline) when is_function(dx, 6) do
dx = dx.(image, prev_x, prev_width, x, dx, baseline)
get_y(image, prev_x, prev_width, x, dx, baseline)
end
def get_x(_image, _prev_x, _prev_width, x, dx, _) when is_integer(x) and is_integer(dx) do
{:ok, x + dx}
end
# Centre align to image
def get_x(image, prev_x, prev_width, :center, dx, _) do
{:ok, prev_x + div(prev_width, 2) - div(Image.width(image), 2) + dx}
end
# Left align to image
def get_x(_image, prev_x, _prev_width, :left, dx, _) do
{:ok, prev_x + dx}
end
# Right align to image
def get_x(image, prev_x, prev_width, :right, dx, _) do
{:ok, prev_x + prev_width - Image.width(image) + dx}
end
# Offset from right edge of image
def get_x(_image, prev_x, prev_width, nil, dx, :right) do
{:ok, prev_x + prev_width + dx}
end
# Offset from left edge of image
def get_x(_image, prev_x, _prev_width, nil, dx, :left) do
{:ok, prev_x + dx}
end
# Default to right edge of image if no baseline
def get_x(image, prev_x, prev_width, nil, dx, nil) do
get_x(image, prev_x, prev_width, nil, dx, :left)
end
def get_x(_image, _prev_x, _prev_width, x, _dx, _baseline) do
{:error, "Invalid value for :x, found #{inspect(x)}"}
end
@doc false
def get_y(image, prev_y, prev_height, y, dy, baseline) when is_function(y, 6) do
y = y.(image, prev_y, prev_height, y, dy, baseline)
get_y(image, prev_y, prev_height, y, dy, baseline)
end
def get_y(image, prev_y, prev_height, y, dy, baseline) when is_function(dy, 6) do
dy = dy.(image, prev_y, prev_height, y, dy, baseline)
get_y(image, prev_y, prev_height, y, dy, baseline)
end
def get_y(_image, _prev_y, _prev_width, y, dy, _) when is_integer(y) and is_integer(dy) do
{:ok, y + dy}
end
# Middle align to image
def get_y(image, prev_y, prev_height, :middle, dy, _) do
{:ok, prev_y + div(prev_height, 2) - div(Image.height(image), 2) + dy}
end
# Top align to image
def get_y(_image, prev_y, _prev_height, :top, dy, _) do
{:ok, prev_y + dy}
end
# Bottom align to image
def get_y(image, prev_y, prev_height, :bottom, dy, _) do
{:ok, prev_y + prev_height - Image.height(image) + dy}
end
# Offset from bottom edge of image
def get_y(_image, prev_y, prev_height, nil, dy, :bottom) do
{:ok, prev_y + prev_height + dy}
end
# Offset from top edge of image
def get_y(_image, prev_y, _prev_height, nil, dy, :top) do
{:ok, prev_y + dy}
end
# Default to bottom aligned
def get_y(image, prev_y, prev_height, nil, dy, nil) do
get_y(image, prev_y, prev_height, nil, dy, :bottom)
end
def get_y(_image, _prev_y, _prev_height, y, _dy, _baseline) do
{:error, "Invalid value for :y, found #{inspect(y)}"}
end
def default_composit_options do
%{
x: nil,
y: nil,
dx: 0,
dy: 0,
x_baseline: nil,
y_baseline: nil,
blend_mode: Image.BlendMode.default_blend_mode()
}
end
end