Current section

Files

Jump to
mogrify lib mogrify.ex
Raw

lib/mogrify.ex

defmodule Mogrify do
alias Mogrify.Image
@doc """
Opens image source
"""
def open(path) do
path = Path.expand(path)
unless File.regular?(path), do: raise(File.Error)
%Image{path: path, ext: Path.extname(path)}
end
@doc """
Saves modified image
"""
def save(image, path) do
File.cp!(image.path, path)
%{image | path: path}
end
@doc """
Makes a copy of original image
"""
def copy(image) do
name = Path.basename(image.path)
random = :crypto.rand_uniform(100_000, 999_999)
temp = Path.join(System.tmp_dir, "#{random}-#{name}")
File.cp!(image.path, temp)
Map.put(image, :path, temp)
end
@doc """
Provides detailed information about the image
"""
def verbose(image) do
{output, 0} = run(image.path, "verbose")
info = Regex.named_captures(~r/\S+ (?<format>\S+) (?<width>\d+)x(?<height>\d+)/, output)
info = Enum.reduce(info, %{}, fn ({key, value}, acc) ->
{key, value} = {String.to_atom(key), String.downcase(value)}
Map.put(acc, key, value)
end)
Map.merge(image, info)
end
@doc """
Converts the image to the image format you specify
"""
def format(image, format) do
{_, 0} = run(image.path, "format", format)
ext = ".#{String.downcase(format)}"
rootname = Path.rootname(image.path, image.ext)
%{image | path: "#{rootname}#{ext}", ext: ext}
end
@doc """
Resizes the image with provided geometry
"""
def resize(image, params) do
{_, 0} = run(image.path, "resize", params)
image |> verbose
end
@doc """
Extends the image to the specified dimensions
"""
def extent(image, params) do
{_, 0} = run(image.path, "extent", params)
image |> verbose
end
@doc """
Resize the image to fit within the specified dimensions while retaining
the original aspect ratio. Will only resize the image if it is larger than the
specified dimensions. The resulting image may be shorter or narrower than specified
in the smaller dimension but will not be larger than the specified values.
"""
def resize_to_limit(image, params) do
resize(image, "#{params}>")
end
@doc """
Resize the image to fit within the specified dimensions while retaining
the aspect ratio of the original image. If necessary, crop the image in the
larger dimension.
"""
def resize_to_fill(image, params) do
[_, width, height] = Regex.run(~r/(\d+)x(\d+)/, params)
image = Mogrify.verbose(image)
{width, _} = Float.parse width
{height, _} = Float.parse height
{cols, _} = Float.parse image.width
{rows, _} = Float.parse image.height
if width != cols || height != rows do
scale_x = width/cols #.to_f
scale_y = height/rows #.to_f
if scale_x >= scale_y do
cols = (scale_x * (cols + 0.5)) |> Float.round
rows = (scale_x * (rows + 0.5)) |> Float.round
image = resize image, "#{cols}"
else
cols = (scale_y * (cols + 0.5)) |> Float.round
rows = (scale_y * (rows + 0.5)) |> Float.round
image = resize image, "x#{rows}"
end
end
if cols != width || rows != height do
image = extent(image, params)
end
image
end
defp run(path, option, params \\ nil) do
args = ~w(-#{option} #{params} #{String.replace(path, " ", "\\ ")})
System.cmd "mogrify", args, stderr_to_stdout: true
end
end