View Source Vix.Vips.Image (vix v0.30.0)

Functions for reading and writing images as well as accessing and updating image metadata.

Access syntax (slicing)

Vix images implement Elixir's access syntax. This allows developers to slice images and easily access sub-dimensions and values.

Integer

Access accepts integers. Integers will extract an image band using parameter as index:

#=> {:ok, i} = Image.new_from_file("./test/images/puppies.jpg")
{:ok, %Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153539>}}
#=> i[0]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153540>}

If a negative index is given, it accesses the band from the back:

#=> i[-1]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153540>}

Out of bound access will throw an ArgumentError exception:

#=> i[-4]
** (ArgumentError) Invalid band requested. Found -4

Range

Access also accepts ranges. Ranges in Elixir are inclusive:

#=> i[0..1]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153641>}

Ranges can receive negative positions and they will read from the back. In such cases, the range step must be explicitly given (on Elixir 1.12 and later) and the right-side of the range must be equal or greater than the left-side:

#=> i[0..-1//1]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153703>}

To slice across multiple dimensions, you can wrap the ranges in a list. The list will be of the form [with_slice, height_slice, band_slice].

# Returns an image that slices a 10x10 pixel square
# from the top left of the image with three bands
#=> i[[0..9, 0..9, 0..3]]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153738>}

If number of dimensions are less than 3 then remaining dimensions are returned in full

# If `i` size is 100x100 with 3 bands
#=> i[[0..9, 0..9]] # equivalent to `i[[0..9, 0..9, 0..2]]`
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153740>}

#=> i[[0..9]] # equivalent to `i[[0..9, 0..99, 0..2]]`
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153703>}

Slices can include negative ranges in which case the indexes are calculated from the right and bottom of the image.

# Slices the bottom right 10x10 pixels of the image
# and returns all bands.
#=> i[[-10..-1, -10..-1]]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153742>}

Slice can mix integers and ranges

# Slices the bottom right 10x1 pixels of the image
# and returns all bands.
#=> i[[-10..-1, -1]]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153742>}

Keyword List

Access also accepts keyword list. Where key can be any of width, height, band. and value must be an integer, range. This is useful for complex scenarios when you want omit dimensions arbitrary dimensions.

# Slices an image with height 10 with max width and all bands
#=> i[[height: 0..10]]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153742>}

# Slices an image with single band 1
#=> i[[band: 1]]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153742>}

# Slices the bottom right 10x10 pixels of the image
# and returns all bands.
#=> i[[width: -10..-1, height: -10..-1]]
%Vix.Vips.Image{ref: #Reference<0.2448791511.2685009949.153742>}

Summary

Types

t()

Represents an instance of VipsImage

Functions

Get "bands" of the image

Get "coding" of the image

Get "filename" of the image

Get "format" of the image

Returns the pixel value for the passed position

Same as get_pixel/3. Returns the pixel value on success or raise the error.

Return a boolean indicating if an image has an alpha band.

Get all image header field names.

Get image header value.

Get image header value as string.

Get all image header data as map. Headers includes metadata such as image height, width, bands.

Get "height" of the image

Get "interpretation" of the image

Get "mode" of the image

Mutate an image in-place. You have to pass a function which takes MutableImage as argument. Inside the callback function, you can call functions which modify the image, such as setting or removing metadata. See Vix.Vips.MutableImage

Get "n-pages" of the image

Create a new image from raw pixel data

Create a new image from formatted binary

Create a new image from Enumerable.

Opens path for reading, returns an instance of Vix.Vips.Image.t/0

Create a new image based on an existing image with each pixel set to value

Make a VipsImage from 1D or 2D list.

Make a VipsImage which, when written to, will create a temporary file on disc.

Get "offset" of the image

Get "orientation" of the image

Get "page-height" of the image

Get "scale" of the image

Returns list of supported extension for saving the image.

Converts an Image to a nested list.

Get "width" of the image

Returns raw pixel data of the image as binary term

Returns vips_image as binary based on the format specified by suffix.

Write vips_image to a file.

Creates a Stream from Image.

Returns raw pixel data of the image as Vix.Tensor

Get "xoffset" of the image

Get "xres" of the image

Get "yoffset" of the image

Get "yres" of the image

Types

@type t() :: %Vix.Vips.Image{ref: reference()}

Represents an instance of VipsImage

Functions

@spec bands(t()) :: pos_integer() | no_return()

Get "bands" of the image

More details

See libvips docs for more details regarding bands function

@spec coding(t()) :: Vix.Vips.Operation.vips_coding() | no_return()

Get "coding" of the image

More details

See libvips docs for more details regarding coding function

@spec filename(t()) :: String.t() | no_return()

Get "filename" of the image

More details

See libvips docs for more details regarding filename function

Get "format" of the image

More details

See libvips docs for more details regarding format function

@spec get_pixel(t(), x :: non_neg_integer(), y :: non_neg_integer()) ::
  {:ok, [term()]} | {:error, term()}

Returns the pixel value for the passed position

Pixel value is a list of numbers. Size of the list depends on the number of bands in the image and number type will depend on the band format (see: Vix.Vips.Operation.vips_band_format/0).

For example for RGBA image with unsigned char band format the return value will be a list of integer of size 4.

This function is similar to Vix.Vips.Operation.getpoint/3, getpoint always returns the value as float but get_pixel returns based on the image band format.

Caution

Loop through lot of pixels using get_pixel can be expensive. Use extract_area or Access syntax (slicing) instead

@spec get_pixel!(t(), x :: non_neg_integer(), y :: non_neg_integer()) ::
  [term()] | no_return()

Same as get_pixel/3. Returns the pixel value on success or raise the error.

@spec has_alpha?(t()) :: boolean() | no_return()

Return a boolean indicating if an image has an alpha band.

Example

  {:ok, im} = Image.new_from_file("puppies.jpg")

  has_alpha? = Image.has_alpha?(im)
Link to this function

header_field_names(image)

View Source
@spec header_field_names(t()) :: {:ok, [String.t()]} | {:error, term()}

Get all image header field names.

See https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-fields for more details

Link to this function

header_value(image, name)

View Source
@spec header_value(t(), String.t()) ::
  {:ok, integer() | float() | String.t() | binary() | list() | atom()}
  | {:error, term()}

Get image header value.

This is a generic function to get header value.

Casts the value to appropriate type. Returned value can be integer, float, string, binary, list. Use Vix.Vips.Image.header_value_as_string/2 to get string representation of any header value.

{:ok, width} = Image.header_value(vips_image, "width")
Link to this function

header_value_as_string(image, name)

View Source
@spec header_value_as_string(t(), String.t()) :: {:ok, String.t()} | {:error, term()}

Get image header value as string.

This is generic method to get string representation of a header value. If value is VipsBlob, then it returns base64 encoded data.

See: https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-as-string

@spec headers(t()) :: %{
  width: pos_integer() | nil,
  height: pos_integer() | nil,
  bands: pos_integer() | nil,
  xres: float() | nil,
  yres: float() | nil,
  xoffset: integer() | nil,
  yoffset: integer() | nil,
  filename: String.t() | nil,
  mode: String.t() | nil,
  scale: float() | nil,
  offset: float() | nil,
  "page-height": integer() | nil,
  "n-pages": integer() | nil,
  orientation: integer() | nil,
  interpretation: Vix.Vips.Operation.vips_interpretation() | nil,
  coding: Vix.Vips.Operation.vips_coding() | nil,
  format: Vix.Vips.Operation.vips_band_format() | nil
}

Get all image header data as map. Headers includes metadata such as image height, width, bands.

If a header does not exists then value for that header will be set to nil.

See https://libvips.github.io/libvips/API/current/libvips-header.html for more details.

@spec height(t()) :: pos_integer() | no_return()

Get "height" of the image

More details

See libvips docs for more details regarding height function

@spec interpretation(t()) :: Vix.Vips.Operation.vips_interpretation() | no_return()

Get "interpretation" of the image

More details

See libvips docs for more details regarding interpretation function

@spec mode(t()) :: String.t() | no_return()

Get "mode" of the image

More details

See libvips docs for more details regarding mode function

@spec mutate(t(), (Vix.Vips.MutableImage.t() -> any())) ::
  {:ok, t()} | {:ok, {t(), any()}} | {:error, term()}

Mutate an image in-place. You have to pass a function which takes MutableImage as argument. Inside the callback function, you can call functions which modify the image, such as setting or removing metadata. See Vix.Vips.MutableImage

Return value of the callback must be one of:

  • The mutated image passed to the callback or
  • :ok or
  • {:ok, some_result}

Call returns updated image.

Example

  {:ok, im} = Image.new_from_file("puppies.jpg")

  {:ok, new_im} =
    Image.mutate(im, fn mut_image ->
      :ok = MutableImage.update(mut_image, "orientation", 0)
      :ok = MutableImage.set(mut_image, "new-field", :gint, 0)
    end)
@spec n_pages(t()) :: integer() | no_return()

Get "n-pages" of the image

More details

See libvips docs for more details regarding n_pages function

Link to this function

new_from_binary(bin, width, height, bands, band_format)

View Source
@spec new_from_binary(
  binary(),
  pos_integer(),
  pos_integer(),
  pos_integer(),
  Vix.Vips.Operation.vips_band_format()
) :: {:ok, t()} | {:error, term()}

Create a new image from raw pixel data

Creates an image by wrapping passed raw pixel data. This function does not copy the passed binary, instead it just creates a reference to the binary term (zero-copy). So this function is very efficient.

This function is useful when you are getting raw pixel data from some other library like eVision or Nx and want to perform some operation on it using Vix.

Binary should be sequence of pixel data, for example: RGBRGBRGB. and order should be left-to-right, top-to-bottom.

bands should be number values which represent the each pixel. For example: if each pixel is RGB then bands will be 3. If each pixel is RGBA then bands will be 4. band_format refers to type of each band. Usually it will be :VIPS_FORMAT_UCHAR.

bin should be raw pixel data binary. For loading formatted binary (JPEG, PNG) see new_from_buffer/2.

Endianness

Byte order of the data must be in native endianness. This matters if you are generating or manipulating binary by using bitstring syntax. By default bitstring treat binary byte order as big endian which might not be native. Always use native specifier to ensure. See Elixir docs for more details.

Link to this function

new_from_buffer(bin, opts \\ [])

View Source
@spec new_from_buffer(
  binary(),
  keyword()
) :: {:ok, t()} | {:error, term()}

Create a new image from formatted binary

Create a new image from formatted binary bin. Binary should be an image encoded in a format such as JPEG. It tries to recognize the format by checking the binary.

If you already know the image format of bin then you can just use corresponding loader operation function directly from Vix.Vips.Operation instead. For example to load jpeg, you can use Vix.Vips.Operation.jpegload_buffer/2

bin should be formatted binary (ie. JPEG, PNG etc). For loading unformatted binary (raw pixel data) see new_from_binary/5.

Optional param opts is passed to the image loader. Options available depend on the file format. You can find all options available like this:

$ vips jpegload_buffer

Not all loaders support load from buffer, but at least JPEG, PNG and TIFF images will work.

Link to this function

new_from_enum(enum, opts \\ "")

View Source
@spec new_from_enum(Enumerable.t(), String.t()) :: {:ok, t()} | {:error, term()}

Create a new image from Enumerable.

Returns an image which will lazily pull data from passed Enumerable. enum should be stream of bytes of an encoded image such as JPEG. This functions recognizes the image format and metadata by reading starting bytes and wraps passed Enumerable as an image. Remaining bytes are read on-demand.

Useful when working with big images. Where you don't want to load complete input image data to memory.

{:ok, image} =
  File.stream!("puppies.jpg", [], 1024) # or read from s3, web-request
  |> Image.new_from_enum()

:ok = Image.write_to_file(image, "puppies.png")

Optional param opts string is passed to the image loader. It is a string of the format "[name=value,...]".

Image.new_from_enum(stream, "[shrink=2]")

Will read the stream with downsampling by a factor of two.

The full set of options available depend upon the image format. You can find all options available at the command-line. To see a summary of the available options for the JPEG loader:

$ vips jpegload_source
@spec new_from_file(String.t()) :: {:ok, t()} | {:error, term()}

Opens path for reading, returns an instance of Vix.Vips.Image.t/0

It can load files in many image formats, including VIPS, TIFF, PNG, JPEG, FITS, Matlab, OpenEXR, CSV, WebP, Radiance, RAW, PPM and others.

Load options may be appended to filename as "[name=value,...]". For example:

Image.new_from_file("fred.jpg[shrink=2]")

Will open "fred.jpg", downsampling by a factor of two.

The full set of options available depend upon the load operation that will be executed. Try something like:

$ vips jpegload

at the command-line to see a summary of the available options for the JPEG loader.

If you want more control over the loader, Use specific format loader from Vix.Vips.Operation. For example for jpeg use Vix.Vips.Operation.jpegload/2

Loading is fast: only enough of the image is loaded to be able to fill out the header. Pixels will only be decompressed when they are needed.

Link to this function

new_from_image(image, value)

View Source
@spec new_from_image(t(), [number()]) :: {:ok, t()} | {:error, term()}

Create a new image based on an existing image with each pixel set to value

Creates a new image with width, height, format, interpretation, resolution and offset taken from the input image, but with each band set from value.

Link to this function

new_from_list(list, optional \\ [])

View Source
@spec new_from_list(
  [[number()]] | [number()] | Range.t(),
  keyword()
) :: {:ok, t()} | {:error, term()}

Make a VipsImage from 1D or 2D list.

If list is a single dimension then an image of height 1 will be with list content as values.

If list is 2D then 2D image will be created.

Output image will always be a one band image with double format.

# 1D list
{:ok, img2} = Image.new_from_list([0, 1, 0])

# 2D list
{:ok, img} = Image.new_from_list([[0, 1, 0], [1, 1, 1], [0, 1, 0]])

Optional

  • scale - Default: 1
  • offset - Default: 0
Link to this function

new_matrix_from_array(width, height, list, optional \\ [])

View Source
@spec new_matrix_from_array(integer(), integer(), [list()], keyword()) ::
  {:ok, t()} | {:error, term()}

Make a VipsImage from 2D list.

This is a convenience function makes an image which is a matrix: a one-band VIPS_FORMAT_DOUBLE image held in memory. Useful for vips operations such as conv.

{:ok, mask} = Image.new_matrix_from_array(3, 3, [[0, 1, 0], [1, 1, 1], [0, 1, 0]])

Optional

  • scale - Default: 1
  • offset - Default: 0
@spec new_temp_file(String.t()) :: {:ok, t()} | {:error, term()}

Make a VipsImage which, when written to, will create a temporary file on disc.

The file will be automatically deleted when the image is destroyed. format is something like "%s.v" for a vips file.

The file is created in the temporary directory. This is set with the environment variable TMPDIR. If this is not set, then on Unix systems, vips will default to /tmp. On Windows, vips uses GetTempPath() to find the temporary directory.

vips_image = Image.new_temp_file("%s.v")
@spec offset(t()) :: float() | no_return()

Get "offset" of the image

More details

See libvips docs for more details regarding offset function

@spec orientation(t()) :: integer() | no_return()

Get "orientation" of the image

More details

See libvips docs for more details regarding orientation function

@spec page_height(t()) :: integer() | no_return()

Get "page-height" of the image

More details

See libvips docs for more details regarding page_height function

@spec scale(t()) :: float() | no_return()

Get "scale" of the image

More details

See libvips docs for more details regarding scale function

Link to this function

supported_saver_suffixes()

View Source
@spec supported_saver_suffixes() :: {:ok, [String.t()]} | {:error, term()}

Returns list of supported extension for saving the image.

Supported suffix can be used to save image in a particular format. See write_to_file/2.

Note that the image format supported for saving the image and the format supported for loading image might be different. For example SVG format can be loaded but can not be saved.

@spec to_list(t()) :: {:ok, [[[number()]]]} | {:error, term()}

Converts an Image to a nested list.

Returns a nested list of the shape height x width x band. For example for an image with height 10, width 5, and 3 bands returned value will be a list of length 10 (height), with each element will be a list of length 5 (height), and each element inside that will be a list of length 3 (bands).

Caution

This is meant to be used for very small images such as histograms, and matrix. Depending on the image size it can generate and return a large list leading to performance issues.

histogram =
  Vix.Vips.Operation.black!(10, 50)
  |> Vix.Vips.Operation.hist_find!()

list = Vix.Vips.Image.to_list(histogram)
@spec width(t()) :: pos_integer() | no_return()

Get "width" of the image

More details

See libvips docs for more details regarding width function

@spec write_to_binary(t()) :: {:ok, binary()} | {:error, term()}

Returns raw pixel data of the image as binary term

Please check write_to_tensor for more details. This function just returns the data instead of the Vix.Tensor struct.

Prefer using write_to_tensor instead of this function. This is only useful if you already know the details about the returned binary blob. Such as height, width and bands.

Link to this function

write_to_buffer(image, suffix)

View Source
@spec write_to_buffer(t(), String.t()) :: {:ok, binary()} | {:error, term()}

Returns vips_image as binary based on the format specified by suffix.

This function is similar to write_to_file but instead of writing the output to the file, it returns it as a binary.

Currently only TIFF, JPEG and PNG formats are supported.

Save options may be encoded in the filename. For example:

Image.write_to_buffer(vips_image, ".jpg[Q=90]")

The full set of save options depend on the selected saver. You can get list of available options for the saver

$ vips jpegsave
Link to this function

write_to_file(image, path)

View Source
@spec write_to_file(t(), String.t()) :: :ok | {:error, term()}

Write vips_image to a file.

A saver is selected based on image extension in path. You can get list of supported extensions by supported_saver_suffixes/0.

Save options may be encoded in the filename. For example:

Image.write_to_file(vips_image, "fred.jpg[Q=90]")

The full set of save options depend on the selected saver. You can check the supported options for a saver by checking docs for the particular format save function in Operation module. For example, for you jpeg, Vix.Vips.Operation.jpegsave/2.

If you want more control over the saver, Use specific format saver from Vix.Vips.Operation. For example for jpeg use Vix.Vips.Operation.jpegsave/2

Link to this function

write_to_stream(image, suffix)

View Source
@spec write_to_stream(t(), String.t()) :: Enumerable.t()

Creates a Stream from Image.

Returns a Stream which will lazily pull data from passed image.

Useful when working with big images. Where you don't want to keep complete output image in memory.

{:ok, image} = Image.new_from_file("puppies.jpg")

:ok =
  Image.write_to_stream(image, ".png")
  |> Stream.into(File.stream!("puppies.png")) # or write to S3, web-request
  |> Stream.run()

Second param suffix determines the format of the output stream. Save options may be appended to the suffix as "[name=value,...]".

Image.write_to_stream(vips_image, ".jpg[Q=90]")

Options are specific to save operation. You can find out all available options for the save operation at command line. For example:

$ vips jpegsave_target
@spec write_to_tensor(t()) :: {:ok, Vix.Tensor.t()} | {:error, term()}

Returns raw pixel data of the image as Vix.Tensor

VIPS images are three-dimensional arrays, the dimensions being width, height and bands.

Each dimension can be up to 2 ** 31 pixels (or band elements). An image has a format, meaning the machine number type used to represent each value. VIPS supports 10 formats, from 8-bit unsigned integer up to 128-bit double complex.

In VIPS, images are uninterpreted arrays, meaning that from the point of view of most operations, they are just large collections of numbers. There's no difference between an RGBA (RGB with alpha) image and a CMYK image, for example, they are both just four-band images.

This function is intended to support interoperability of image data between different libraries. Since the array is created as a NIF resource it will be correctly garbage collected when the last reference falls out of scope.

Libvips might run all the operations to produce the pixel data depending on the caching mechanism and how image is built.

Endianness

Returned binary term will be in native endianness. By default bitstring treats byte order as big endian which might not be native. Always use native specifier to ensure. See Elixir docs for more details.

@spec xoffset(t()) :: integer() | no_return()

Get "xoffset" of the image

More details

See libvips docs for more details regarding xoffset function

@spec xres(t()) :: float() | no_return()

Get "xres" of the image

More details

See libvips docs for more details regarding xres function

@spec yoffset(t()) :: integer() | no_return()

Get "yoffset" of the image

More details

See libvips docs for more details regarding yoffset function

@spec yres(t()) :: float() | no_return()

Get "yres" of the image

More details

See libvips docs for more details regarding yres function