View Source Vix
Vix is Elixir extension for vips image processing library.
why-vix
Why Vix
Vix is a NIF based bindings library for libvips. Vix does not spawn OS processes for the operations like other libraries. And it can make full use of libvips optimizations such as joining of operations in the pipeline, cache etc.
Operation bindings are generated using vips introspection, so the generated documentation and bindings always matches the vips version installed.
Check vips operation documentation for the list of available operations and spec.
what-is-vips
What is Vips
From vips documentation:
libvips is a demand-driven, horizontally threaded image processing library. Compared to similar libraries, libvips runs quickly and uses little memory.
introduction
Introduction
Easiest way to get started or to explore the operations is to run Introduction Livebook.
# print vips version
IO.puts("Version: " <> Vix.Vips.version())
# contains image read/write functions
alias Vix.Vips.Image
# reading image from a file. Note that image is not actually loaded to the memory at this point.
# img is `%Image{}` struct.
{:ok, img} = Image.new_from_file("~/Downloads/kitty.png")
# You can also load image from binary. This let us to work images without touching file system.
# It tires to guess image format from the binary and uses correct loader.
bin = File.read!("~/Downloads/kitty.png")
{:ok, %Image{} = img} = Image.new_from_buffer(bin)
# If you know image format beforehand then you can use appropriate function from
# `Vix.Vips.Operation`. For example to load png you can use `Vix.Vips.Operation.pngload_buffer/2`.
bin = File.read!("~/Downloads/kitty.png")
{:ok, {img, _flags}} = Vix.Vips.Operation.pngload_buffer(bin)
# writing `Image` to a file.
# Image type selected based on the image path extension. See documentation for more options
:ok = Image.write_to_file(img, "kitty.jpg[Q=90]")
# let's print image dimensions
IO.puts("Width: #{Image.width(img)}")
IO.puts("Height: #{Image.height(img)}")
# Operations
# contains image processing operations
alias Vix.Vips.Operation
# getting a rectangular region from the image (crop)
{:ok, extract_img} = Operation.extract_area(img, 100, 50, 200, 200)
# create image thumbnail.
# this function accepts many optional parameters, see: https://libvips.github.io/libvips/API/current/Using-vipsthumbnail.md.html
# also see `Operation.thumbnail/3` which accepts image path
{:ok, thumb} = Operation.thumbnail_image(img, 100)
# resize image to 400x600. `resize` function accepts scaling factor.
# Skip `vscale` if you want to preserve aspect ratio
hscale = 400 / Image.width(img)
vscale = 600 / Image.height(img)
{:ok, resized_img} = Operation.resize(img, hscale, vscale: vscale)
# flip image
{:ok, flipped_img} = Operation.flip(img, :VIPS_DIRECTION_HORIZONTAL)
# Gaussian blur
{:ok, blurred_img} = Operation.gaussblur(img, 5)
# convert image to a grayscale image
{:ok, bw_img} = Operation.colourspace(img, :VIPS_INTERPRETATION_B_W)
# adding gray border
{:ok, extended_img} =
Operation.embed(img, 10, 10, Image.width(img) + 20, Image.height(img) + 20,
extend: :VIPS_EXTEND_BACKGROUND,
background: [128]
)
# rotate image 90 degree clockwise
{:ok, rotated_img} = Operation.rot(img, :VIPS_ANGLE_D90)
# join two images horizontally
{:ok, main_img} = Image.new_from_file("~/Downloads/kitten.svg")
{:ok, joined_img} = Operation.join(img, main_img, :VIPS_DIRECTION_HORIZONTAL, expand: true)
# render text as image
# see https://libvips.github.io/libvips/API/current/libvips-create.html#vips-text for more details
{:ok, {text, _}} = Operation.text(~s(<b>Vix</b> is <span foreground="red">awesome!</span>), dpi: 300, rgba: true)
# add text to an image
{:ok, img_with_text} = Operation.composite2(img, text, :VIPS_BLEND_MODE_OVER, x: 50, y: 20)
## Creating GIF
black = Operation.black!(500, 500, bands: 3)
# create images with different grayscale
frames = Enum.map(1..255//10, fn n ->
Operation.linear!(black, [1], [n,n,n])
end)
{:ok, joined_img} = Operation.arrayjoin(frames, across: 1)
# set frame delay metadata. See `Image.mutate` documentation for more details
{:ok, joined_img} =
Image.mutate(joined_img, fn mut_img ->
frame_delay = List.duplicate(100, length(frames))
:ok = Vix.Vips.MutableImage.set(mut_img, "delay", :VipsArrayInt, frame_delay)
end)
:ok = Operation.gifsave(joined_img, Path.expand("~/Downloads/bw.gif"), "page-height": 500)
The libvips reference manual has more detailed documentation about the operations.
bonus
Bonus
Livebook implementing picture language defined in Structural and Interpretation of Computer Programs section 2.2.4
warning
Warning
This library is experimental and the code is not well tested, so you might experience crashes.
requirements
Requirements
libvips with development headers
- macOS: using brew
brew install libvips
- Linux: using deb
apt install libvips-dev
For more details see https://www.libvips.org/install.html
- macOS: using brew
pkg-config
c compiler
installation
Installation
def deps do
[
{:vix, "~> x.x.x"}
]
end
todo
TODO
- [ ] support mutable operations such as draw*