View Source Vix.Operator (vix v0.33.1)

Provides an intuitive and readable interface for performing image processing operations by overriding common mathematical and relational operators.

This module simplifies complex image processing pipelines by allowing you to use familiar operators, such as +, -, *, /, and comparison operators (==, >=, etc.), directly with images, numbers, and lists of numbers (pixels). It also includes utility functions for logical operations and validation, like all?/2.

Key Features

  • Bitwise Operations: Perform Bitwise Boolean operations such as &&, ||, and xor between images and numbers.
  • Arithmetic Operations: Use operators such as +, -, *, /, and ** to perform pixel-wise operations between images, numbers, or lists of numbers.
  • Comparison Operations: Compare pixel values using operators like ==, !=, <, <=, >, and >=, returning the result as a new image.
  • Logical Validation: Check pixel values for truthiness (e.g., 255 for true, 0 for false) using all?/2.

Example Usage

defmodule Example do
 alias Vix.Vips.Operation

 def demo_operations do
   # Import only the required operators for readability and clarity
   use Vix.Operator, only: [+: 2, -: 2, *: 2, /: 2, ==: 2, all?: 2]

   # Create a black image (100x100, 3 bands)
   black = Image.build_image!(100, 100, [0, 0, 0])

   # Add constant values to pixels
   grey1 = black + 125
   grey2 = black + [125, 125, 125]

   # Pixel-wise addition: [255, 255, 255] + [0, 0, 0]
   result_image = white + grey1

   # Create a white image
   white = Image.build_image!(100, 100, [255, 255, 255])

   result = (black + 255) == white
   true = all?(result, true)
 end
end

Summary

Functions

Performs Bitwise Boolean AND Operation (&&) between Images and numbers, returning the result as an Image.

Performs Power (**) operation between Images, numbers, and lists of numbers (pixels).

Performs Multiplication (*) operation between Images, numbers, and lists of numbers (pixels).

Performs Addition (+) operation between Images, numbers, and lists of numbers (pixels).

Performs Subtraction (-) operation between Images, numbers, and lists of numbers (pixels).

Performs Division (/) operation between Images, numbers, and lists of numbers (pixels).

Performs Not_equal (!=) comparison between Images and numbers, returning the result as an Image.

Performs Less_than (<) comparison between Images and numbers, returning the result as an Image.

Performs Less_than_equal (<=) comparison between Images and numbers, returning the result as an Image.

Performs Equal (==) comparison between Images and numbers, returning the result as an Image.

Performs Greater_than (>) comparison between Images and numbers, returning the result as an Image.

Performs Greater_than_equal (>=) comparison between Images and numbers, returning the result as an Image.

Checks if all of the values are "true" (255) or "false" (0). Useful together with relational operators.

Performs Bitwise Boolean XOR Operation (xor) between Images and numbers, returning the result as an Image.

Performs Bitwise Boolean OR Operation (||) between Images and numbers, returning the result as an Image.

Functions

a && b

@spec (Vix.Vips.Image.t() | number() | [number()]) &&
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec term() && term() :: term()

Performs Bitwise Boolean AND Operation (&&) between Images and numbers, returning the result as an Image.

Overview

The operation handles various input combinations:

  • Image && Image
  • Image && number(s)
  • number(s) && Image
  • non-Image values (falls back to Kernel)

Input Handling

Values are cast up before operations. Float values are converted to integers

Number Inputs

  • Single number: Applied to all image bands uniformly
  • Number list:
    • If list size matches image bands: Each number applies to its respective band
    • If list size does not match the image bands: Either the image bands or the list is scaled up to match the other.

Image Inputs

  • When both inputs are images: Uses Operation.boolean!(a, b, :VIPS_OPERATION_BOOLEAN_AND)

Examples

Image && Image Operations

iex> img = Image.build_image!(2, 1, [0, 255, 0]) && Image.build_image!(2, 1, [0, 255, 255])
iex> Image.shape(img)
{2, 1, 3}
iex> Image.to_list!(img)
[[[0, 255, 0], [0, 255, 0]]]

# Identical Images
iex> (Image.build_image!(2, 2, [2, 4, 8]) && Image.build_image!(2, 2, [2, 4, 8])) |> Image.to_list!()
[[[2, 4, 8], [2, 4, 8]], [[2, 4, 8], [2, 4, 8]]]

# Different dimensions
iex> img = Image.build_image!(1, 1, [2]) && Image.build_image!(1, 2, [2, 4, 8])
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[2, 0, 0]], [[0, 0, 0]]]

Image && Number Operations

# Single number comparison (applies to all bands)
iex> (Image.build_image!(1, 2, [2, 5, 3]) && 6) |> Image.to_list!()
[[[2, 4, 2]], [[2, 4, 2]]]

# Float Comparison
iex> (Image.build_image!(1, 1, [10]) && 6.0) |> Image.to_list!()
[[[2]]]

# List comparison (band-wise)
iex> (Image.build_image!(1, 1, [2, 2]) && [1, 3]) |> Image.to_list!()
[[[0, 2]]]

Reverse Operations

# Number && Image
iex> (10.0 && Image.build_image!(1, 1, [5])) |> Image.to_list!()
[[[0]]]

# List && Image
iex> ([2, 2] && Image.build_image!(1, 1, [1, 3])) |> Image.to_list!()
[[[0, 2]]]

Kernel Fallback

# When neither argument is an image
iex> false && true
false

a ** b

@spec (Vix.Vips.Image.t() | number() | [number()]) **
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec number() ** number() :: number()

Performs Power (**) operation between Images, numbers, and lists of numbers (pixels).

Overview

The operator handles Images, numbers, and lists together with the following rules:

  • Single numbers are applied to all image bands
  • Lists can be matched with image bands
  • Type casting is handled automatically
  • When neither argument is an image, delegates to Kernel.**/2

Behavior

Power Rules

When operating with numbers or lists:

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Bands are scaled up to match each other.

Type Handling

Output Image Band Format:

  • Two images: Cast to smallest common format that can hold result
  • Image + number:
    • Double input → Double output
    • otherwise → Float output

Examples

Basic Image Power Operation

# Raising each pixel of a single-band image to the power of another single-band image
iex> img1 = Image.build_image!(2, 2, [2])
iex> img2 = Image.build_image!(2, 2, [3])
iex> result = img1 ** img2
iex> Image.to_list!(result)
[[[8.0], [8.0]], [[8.0], [8.0]]]

# Raising multi-band image pixels to the power of single-band image
iex> multi_band = Image.build_image!(1, 2, [2, 3, 4])
iex> single_band = Image.build_image!(1, 2, [2])
iex> result = multi_band ** single_band
iex> Image.to_list!(result)
[[[4.0, 9.0, 16.0]], [[4.0, 9.0, 16.0]]]

Image and Number Operations

# Raising all bands of an image to a constant power
iex> img = Image.build_image!(1, 1, [3, 4, 5]) ** 2
iex> Image.to_list!(img)
[[[9.0, 16.0, 25.0]]]

# Raising image pixels to a fractional power
iex> img = Image.build_image!(1, 1, [16]) ** 0.5
iex> Image.to_list!(img)
[[[4.0]]]

List Operations

# List matching image bands
iex> img = Image.build_image!(1, 2, [2, 3]) ** [3, 2]
iex> Image.to_list!(img)
[[[8.0, 9.0]], [[8.0, 9.0]]]

# List larger than bands (expands single-band image)
iex> img = Image.build_image!(1, 2, [2]) ** [3, 4, 5]
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[8.0, 16.0, 32.0]], [[8.0, 16.0, 32.0]]]

Reverse Operations

# Number on the left side
iex> img = 2 ** Image.build_image!(1, 2, [3, 4])
iex> Image.to_list!(img)
[[[8.0, 16.0]], [[8.0, 16.0]]]

# List on the left side
iex> img = [2, 3, 4] ** Image.build_image!(1, 2, [2])
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[4.0, 9.0, 16.0]], [[4.0, 9.0, 16.0]]]

Type Casting Examples

# Always returns float output
iex> img = Image.build_image!(2, 2, [3]) ** 2
iex> Image.format(img)
:VIPS_FORMAT_FLOAT

Fallback Behavior

# Standard Kernel.** behavior when no images involved
iex> 2 ** 3
8

a * b

@spec (Vix.Vips.Image.t() | number() | [number()]) *
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec number() * number() :: number()

Performs Multiplication (*) operation between Images, numbers, and lists of numbers (pixels).

Overview

The operator handles Images, numbers, and lists together with the following rules:

  • Single numbers are applied to all image bands
  • Lists can be matched with image bands
  • Type casting is handled automatically
  • When neither argument is an image, delegates to Kernel.*/2

Behavior

Multiplication Rules

When operating with numbers or lists:

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Bands are scaled up to match each other.

Type Handling

Output Image Band Format:

  • Two images: Cast to smallest common format that can hold result
  • Image + number:
    • Complex input → Complex output
    • Double input → Double output
    • otherwise → Float output

Examples

Basic Image Multiplication

# Multiplying two single-band images
iex> img1 = Image.build_image!(2, 2, [3])
iex> img2 = Image.build_image!(2, 2, [4])
iex> result = img1 * img2
iex> Image.to_list!(result)
[[[12], [12]], [[12], [12]]]

# Multiplying images with different bands
iex> multi_band = Image.build_image!(1, 2, [2, 3, 4])
iex> single_band = Image.build_image!(1, 2, [5])
iex> result = multi_band * single_band
iex> Image.to_list!(result)
[[[10, 15, 20]], [[10, 15, 20]]]

Image and Number Operations

# Multiplying all bands by a number
iex> img = Image.build_image!(1, 1, [6, 7, 8]) * 3
iex> Image.to_list!(img)
[[[18.0, 21.0, 24.0]]]

# Multiplying by a float (demonstrates type conversion)
iex> img = Image.build_image!(1, 1, [10]) * 2.5
iex> Image.format(img)
:VIPS_FORMAT_FLOAT
iex> Image.to_list!(img)
[[[25.0]]]

List Operations

# List matching image bands
iex> img = Image.build_image!(1, 2, [2, 3]) * [4, 5]
iex> Image.to_list!(img)
[[[8.0, 15.0]], [[8.0, 15.0]]]

# List larger than bands (expands single-band image)
iex> img = Image.build_image!(1, 2, [3]) * [2, 4, 6]
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[6.0, 12.0, 18.0]], [[6.0, 12.0, 18.0]]]

Reverse Operations

# Number on the left side
iex> img = 10 * Image.build_image!(1, 2, [2, 4])
iex> Image.to_list!(img)
[[[20.0, 40.0]], [[20.0, 40.0]]]

# List on the left side
iex> img = [2, 3, 4] * Image.build_image!(1, 2, [5])
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[10.0, 15.0, 20.0]], [[10.0, 15.0, 20.0]]]

Type Casting Examples

# Integer to float conversion
iex> img = Image.build_image!(2, 2, [4]) * 2.5
iex> Image.format(img)
:VIPS_FORMAT_FLOAT

Fallback Behavior

# Standard Kernel.* behavior when no images involved
iex> 5 * 3
15

a + b

@spec (Vix.Vips.Image.t() | number() | [number()]) +
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec number() + number() :: number()

Performs Addition (+) operation between Images, numbers, and lists of numbers (pixels).

Overview

The operator handles Images, numbers, and lists together with the following rules:

  • Single numbers are applied to all image bands
  • Lists can be matched with image bands
  • Type casting is handled automatically
  • When neither argument is an image, delegates to Kernel.+/2

Behavior

Addition Rules

When operating with numbers or lists:

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Bands are scaled up to match each other.

Type Handling

Output Image Band Format:

  • Two images: Cast to smallest common format that can hold result
  • Image + number:
    • Complex input → Complex output
    • Double input → Double output
    • otherwise → Float output

Examples

Basic Image Addition

# Adding two single-band images
iex> img1 = Image.build_image!(2, 2, [10])
iex> img2 = Image.build_image!(2, 2, [20])
iex> result = img1 + img2
iex> Image.to_list!(result)
[[[30], [30]], [[30], [30]]]

# Adding images with different bands
iex> multi_band = Image.build_image!(1, 2, [10, 20, 30])
iex> single_band = Image.build_image!(1, 2, [5])
iex> result = multi_band + single_band
iex> Image.to_list!(result)
[[[15, 25, 35]], [[15, 25, 35]]]

Image and Number Operations

# Adding a number to all bands
iex> img = Image.build_image!(1, 1, [10, 20, 30]) + 5
iex> Image.to_list!(img)
[[[15.0, 25.0, 35.0]]]

# Adding float (demonstrates type conversion)
iex> img = Image.build_image!(1, 1, [10]) + 5.5
iex> Image.format(img)
:VIPS_FORMAT_FLOAT
iex> Image.to_list!(img)
[[[15.5]]]

List Operations

# List matching image bands
iex> img = Image.build_image!(1, 2, [10, 20]) + [5, 10]
iex> Image.to_list!(img)
[[[15.0, 30.0]], [[15.0, 30.0]]]

# List larger than bands (expands single-band image)
iex> img = Image.build_image!(1, 2, [10]) + [5, 10, 15]
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[15.0, 20.0, 25.0]], [[15.0, 20.0, 25.0]]]

Reverse Operations

# Number on the left side
iex> img = 5 + Image.build_image!(1, 2, [10, 20])
iex> Image.to_list!(img)
[[[15.0, 25.0]], [[15.0, 25.0]]]

# List on the left side
iex> img = [5, 10, 15] + Image.build_image!(1, 2, [10])
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[15.0, 20.0, 25.0]], [[15.0, 20.0, 25.0]]]

Type Casting Examples

# Integer to float conversion
iex> img = Image.build_image!(2, 2, [10]) + 5.5
iex> Image.format(img)
:VIPS_FORMAT_FLOAT

Fallback Behavior

# Standard Kernel.+ behavior when no images involved
iex> 5 + 10
15

a - b

@spec (Vix.Vips.Image.t() | number() | [number()]) -
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec number() - number() :: number()

Performs Subtraction (-) operation between Images, numbers, and lists of numbers (pixels).

Overview

The operator handles Images, numbers, and lists together with the following rules:

  • Single numbers are applied to all image bands
  • Lists can be matched with image bands
  • Type casting is handled automatically
  • When neither argument is an image, delegates to Kernel.-/2

Behavior

Subtraction Rules

When operating with numbers or lists:

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Bands are scaled up to match each other.

Type Handling

Output Image Band Format:

  • Two images: Cast to smallest common format that can hold result
  • Image + number:
    • Complex input → Complex output
    • Double input → Double output
    • otherwise → Float output

Examples

Basic Image Subtraction

# Subtracting two single-band images
iex> img1 = Image.build_image!(2, 2, [30])
iex> img2 = Image.build_image!(2, 2, [10])
iex> result = img1 - img2
iex> Image.to_list!(result)
[[[20], [20]], [[20], [20]]]

# Subtracting images with different bands
iex> multi_band = Image.build_image!(1, 2, [30, 40, 50])
iex> single_band = Image.build_image!(1, 2, [10])
iex> result = multi_band - single_band
iex> Image.to_list!(result)
[[[20, 30, 40]], [[20, 30, 40]]]

Image and Number Operations

# Subtracting a number from all bands
iex> img = Image.build_image!(1, 1, [50, 60, 70]) - 20
iex> Image.to_list!(img)
[[[30.0, 40.0, 50.0]]]

# Subtracting a float (demonstrates type conversion)
iex> img = Image.build_image!(1, 1, [50]) - 15.5
iex> Image.format(img)
:VIPS_FORMAT_FLOAT
iex> Image.to_list!(img)
[[[34.5]]]

List Operations

# List matching image bands
iex> img = Image.build_image!(1, 2, [30, 50]) - [10, 20]
iex> Image.to_list!(img)
[[[20.0, 30.0]], [[20.0, 30.0]]]

# List larger than bands (expands single-band image)
iex> img = Image.build_image!(1, 2, [30]) - [5, 10, 15]
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[25.0, 20.0, 15.0]], [[25.0, 20.0, 15.0]]]

Reverse Operations

# Number on the left side
iex> img = 100 - Image.build_image!(1, 2, [30, 50])
iex> Image.to_list!(img)
[[[70.0, 50.0]], [[70.0, 50.0]]]

# List on the left side
iex> img = [50, 60, 70] - Image.build_image!(1, 2, [20])
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[30.0, 40.0, 50.0]], [[30.0, 40.0, 50.0]]]

Type Casting Examples

# Integer to float conversion
iex> img = Image.build_image!(2, 2, [30]) - 10.5
iex> Image.format(img)
:VIPS_FORMAT_FLOAT

Fallback Behavior

# Standard Kernel.- behavior when no images involved
iex> 50 - 20
30

a / b

@spec (Vix.Vips.Image.t() | number() | [number()]) /
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec number() / number() :: number()

Performs Division (/) operation between Images, numbers, and lists of numbers (pixels).

Overview

The operator handles Images, numbers, and lists together with the following rules:

  • Single numbers are applied to all image bands
  • Lists can be matched with image bands
  • Type casting is handled automatically
  • When neither argument is an image, delegates to Kernel.//2

Behavior

Division Rules

When operating with numbers or lists:

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Bands are scaled up to match each other.

Type Handling

Output Image Band Format:

  • Two images: Cast to smallest common format that can hold result
  • Image + number:
    • Complex input → Complex output
    • Double input → Double output
    • otherwise → Float output

Examples

Basic Image Division

# Dividing two single-band images
iex> img1 = Image.build_image!(2, 2, [20])
iex> img2 = Image.build_image!(2, 2, [4])
iex> result = img1 / img2
iex> Image.to_list!(result)
[[[5.0], [5.0]], [[5.0], [5.0]]]

# Dividing images with different bands
iex> multi_band = Image.build_image!(1, 2, [20, 30, 40])
iex> single_band = Image.build_image!(1, 2, [10])
iex> result = multi_band / single_band
iex> Image.to_list!(result)
[[[2.0, 3.0, 4.0]], [[2.0, 3.0, 4.0]]]

# Dividing two images where the divisor contains zero.
# Vix detects division by zero, and sets those pixels to zero in
# the output, without any error or warning.
iex> img1 = Image.build_image!(2, 2, [20])
iex> img2 = Image.build_image!(2, 2, [0])
iex> result = img1 / img2
iex> Image.to_list!(result)
[[[0.0], [0.0]], [[0.0], [0.0]]]

Image and Number Operations

# Dividing all bands by a number
iex> img = Image.build_image!(1, 1, [30, 60, 90]) / 10
iex> Image.to_list!(img)
[[[3.0, 6.0, 9.0]]]

# Dividing by a float (demonstrates type conversion)
iex> img = Image.build_image!(1, 1, [25]) / 2.5
iex> Image.format(img)
:VIPS_FORMAT_FLOAT
iex> Image.to_list!(img)
[[[10.0]]]

List Operations

# List matching image bands
iex> img = Image.build_image!(1, 2, [40, 60]) / [4, 6]
iex> Image.to_list!(img)
[[[10.0, 10.0]], [[10.0, 10.0]]]

# List larger than bands (expands single-band image)
iex> img = Image.build_image!(1, 2, [30]) / [3, 6, 5]
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[10.0, 5.0, 6.0]], [[10.0, 5.0, 6.0]]]

Reverse Operations

# Number on the left side
iex> img = 100 / Image.build_image!(1, 2, [5, 10])
iex> Image.to_list!(img)
[[[20.0, 10.0]], [[20.0, 10.0]]]

# List on the left side
iex> img = [100, 200, 300] / Image.build_image!(1, 2, [10])
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[10.0, 20.0, 30.0]], [[10.0, 20.0, 30.0]]]

Type Casting Examples

# Integer to float conversion
iex> img = Image.build_image!(2, 2, [25]) / 2
iex> Image.format(img)
:VIPS_FORMAT_FLOAT

Fallback Behavior

# Standard Kernel./ behavior when no images involved
iex> 10 / 2
5.0

a != b

@spec (Vix.Vips.Image.t() | number() | [number()]) !=
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec term() != term() :: boolean()

Performs Not_equal (!=) comparison between Images and numbers, returning the result as an Image.

Overview

The operator compares Images and numbers, with the result being an Image where:

  • 0 represents false
  • 255 represents true

When neither argument is an image, the operation delegates to Kernel.!=/2.

Behavior

Image Comparison Rules

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Uses Operation.relational!(a, b, :VIPS_OPERATION_RELATIONAL_NOTEQ). Bands are scaled up to match each other.

Type Handling

  • Images are cast to the smallest common format before comparison
  • Supports mixed numeric types (e.g., integers with floats)
  • Works bidirectionally (image < number and number < image)

Examples

Examples

Basic Image Comparison

# Comparing two images
iex> img = Image.build_image!(2, 2, [10, 15]) != Image.build_image!(2, 2, [15, 15])
iex> Image.shape(img)
{2, 2, 2}
iex> Image.to_list!(img)
[[[255, 0], [255, 0]], [[255, 0], [255, 0]]]

Checking All Pixels

# Using all?/2 to verify if all pixels match condition
iex> img = Image.build_image!(2, 2, [5]) != Image.build_image!(2, 2, [10])
iex> all?(img, true)
true

Multi-band Image Operations

# Same values across all bands (should be false)
iex> (Image.build_image!(10, 10, [10, 20, 30]) != Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
false

# Different values between single and multi-band
iex> (Image.build_image!(10, 10, [20]) != Image.build_image!(10, 10, [10, 10, 10])) |> all?(true)
true

# Multi-band vs single-band with matching values
iex> (Image.build_image!(10, 10, [10, 20, 30]) != Image.build_image!(10, 10, [30])) |> all?(true)
false

Image vs. Number Comparison

# Single number compared to all bands
iex> img = Image.build_image!(1, 2, [5, 10, 20]) != 5
iex> Image.to_list!(img)
[[[0, 255, 255]], [[0, 255, 255]]]

# Comparing with same value (should be false)
iex> (Image.build_image!(10, 10, [10]) != 10) |> all?(true)
false

# Float comparison with different value
iex> (Image.build_image!(10, 10, [10]) != 20.0) |> all?(true)
true

# List comparison with bands
iex> img = Image.build_image!(1, 1, [10, 20]) != [10, 10]
iex> Image.to_list!(img)
[[[0, 255]]]

Reverse Comparison

# Float on the left side
iex> (10.0 != Image.build_image!(10, 10, [20])) |> all?(true)
true

# List on the left side
iex> ([10, 20, 30] != Image.build_image!(10, 10, [20, 30, 40])) |> all?(true)
true

Fallback Behavior

# Standard Kernel.!= behavior when no images involved
iex> 4 != 5
true

a < b

@spec (Vix.Vips.Image.t() | number() | [number()]) <
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec term() < term() :: boolean()

Performs Less_than (<) comparison between Images and numbers, returning the result as an Image.

Overview

The operator compares Images and numbers, with the result being an Image where:

  • 0 represents false
  • 255 represents true

When neither argument is an image, the operation delegates to Kernel.</2.

Behavior

Image Comparison Rules

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Uses Operation.relational!(a, b, :VIPS_OPERATION_RELATIONAL_LESS). Bands are scaled up to match each other.

Type Handling

  • Images are cast to the smallest common format before comparison
  • Supports mixed numeric types (e.g., integers with floats)
  • Works bidirectionally (image < number and number < image)

Examples

Basic Image Comparison

# Comparing two images
iex> img = Image.build_image!(2, 2, [10, 15]) < Image.build_image!(2, 2, [5, 20])
iex> Image.shape(img)
{2, 2, 2}
iex> Image.to_list!(img)
[[[0, 255], [0, 255]], [[0, 255], [0, 255]]]

Checking All Pixels

# Using all?/2 to verify if all pixels match condition
iex> img = Image.build_image!(2, 2, [5]) < Image.build_image!(2, 2, [10])
iex> all?(img, true)
true

Multi-band Image Operations

# Different band count scenarios
iex> (Image.build_image!(10, 10, [10, 20, 30]) < Image.build_image!(10, 10, [20, 30, 40])) |> all?(true)
true
iex> (Image.build_image!(10, 10, [10]) < Image.build_image!(10, 10, [5, 10, 20])) |> all?(true)
false

Image vs. Number Comparison

# Single number compared to all bands
iex> img = Image.build_image!(1, 2, [1, 10, 20]) < 5
iex> Image.to_list!(img)
[[[255, 0, 0]], [[255, 0, 0]]]

# comparing different types
iex> (Image.build_image!(10, 10, [10]) < 20.0) |> all?(true)
true

# List comparison with bands
iex> img = Image.build_image!(1, 1, [10, 20]) < [20, 10]
iex> Image.to_list!(img)
[[[255, 0]]]

Reverse Comparison

# Numbers/lists on the left side
iex> (10.0 < Image.build_image!(10, 10, [20])) |> all?(true)
true
iex> ([10, 20, 30] < Image.build_image!(10, 10, [20, 30, 40])) |> all?(true)
true

Fallback Behavior

# Standard Kernel.< behavior when no images involved
iex> 4 < 5
true

a <= b

@spec (Vix.Vips.Image.t() | number() | [number()]) <=
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec term() <= term() :: boolean()

Performs Less_than_equal (<=) comparison between Images and numbers, returning the result as an Image.

Overview

The operator compares Images and numbers, with the result being an Image where:

  • 0 represents false
  • 255 represents true

When neither argument is an image, the operation delegates to Kernel.<=/2.

Behavior

Image Comparison Rules

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Uses Operation.relational!(a, b, :VIPS_OPERATION_RELATIONAL_LESSEQ). Bands are scaled up to match each other.

Type Handling

  • Images are cast to the smallest common format before comparison
  • Supports mixed numeric types (e.g., integers with floats)
  • Works bidirectionally (image < number and number < image)

Examples

Examples

Basic Image Comparison

# Comparing two images
iex> img = Image.build_image!(2, 2, [10, 15]) <= Image.build_image!(2, 2, [5, 20])
iex> Image.shape(img)
{2, 2, 2}
iex> Image.to_list!(img)
[[[0, 255], [0, 255]], [[0, 255], [0, 255]]]

Checking All Pixels

# Using all?/2 to verify if all pixels match condition
iex> img = Image.build_image!(2, 2, [5]) <= Image.build_image!(2, 2, [10])
iex> all?(img, true)
true

Multi-band Image Operations

# Different band count scenarios
iex> (Image.build_image!(10, 10, [10, 20, 30]) <= Image.build_image!(10, 10, [20, 30, 40])) |> all?(true)
true
iex> (Image.build_image!(10, 10, [20]) <= Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
false
iex> (Image.build_image!(10, 10, [1, 2, 3]) <= Image.build_image!(10, 10, [6])) |> all?(true)
true

Image vs. Number Comparison

# Single number compared to all bands
iex> img = Image.build_image!(1, 2, [5, 10, 15]) <= 5
iex> Image.to_list!(img)
[[[255, 0, 0]], [[255, 0, 0]]]

# Comparing with integer
iex> (Image.build_image!(10, 10, [4]) <= 2) |> all?(true)
false

# Comparing with float
iex> (Image.build_image!(10, 10, [4]) <= 4.0) |> all?(true)
true

# List comparison with bands
iex> img = Image.build_image!(1, 1, [10, 20]) <= [20, 10]
iex> Image.to_list!(img)
[[[255, 0]]]

Reverse Comparison

# Float on the left side
iex> (4.0 <= Image.build_image!(10, 10, [5])) |> all?(true)
true

# List on the left side
iex> ([10, 20, 30] <= Image.build_image!(10, 10, [20, 30, 40])) |> all?(true)
true

Fallback Behavior

# Standard Kernel.<= behavior when no images involved
iex> 4 <= 5
true

a == b

@spec (Vix.Vips.Image.t() | number() | [number()]) ==
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec term() == term() :: boolean()

Performs Equal (==) comparison between Images and numbers, returning the result as an Image.

Overview

The operator compares Images and numbers, with the result being an Image where:

  • 0 represents false
  • 255 represents true

When neither argument is an image, the operation delegates to Kernel.==/2.

Behavior

Image Comparison Rules

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Uses Operation.relational!(a, b, :VIPS_OPERATION_RELATIONAL_EQUAL). Bands are scaled up to match each other.

Type Handling

  • Images are cast to the smallest common format before comparison
  • Supports mixed numeric types (e.g., integers with floats)
  • Works bidirectionally (image < number and number < image)

Examples

Examples

Basic Image Comparison

# Comparing two images
iex> img = Image.build_image!(2, 2, [10, 20]) == Image.build_image!(2, 2, [20, 20])
iex> Image.shape(img)
{2, 2, 2}
iex> Image.to_list!(img)
[[[0, 255], [0, 255]], [[0, 255], [0, 255]]]

Checking All Pixels

# Using all?/2 to verify if all pixels match condition
iex> img = Image.build_image!(2, 2, [10]) == Image.build_image!(2, 2, [10])
iex> all?(img, true)
true

Multi-band Image Operations

# Equal values across all bands
iex> (Image.build_image!(10, 10, [10, 20, 30]) == Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
true

# Single vs multi-band comparison
iex> (Image.build_image!(10, 10, [20]) == Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
false

# Same value across all bands equals single-band image
iex> (Image.build_image!(10, 10, [10, 10, 10]) == Image.build_image!(10, 10, [10])) |> all?(true)
true

Image vs. Number Comparison

# Single number compared to all bands
iex> img = Image.build_image!(1, 2, [5, 10, 20]) == 5
iex> Image.to_list!(img)
[[[255, 0, 0]], [[255, 0, 0]]]

# Non-matching comparison
iex> (Image.build_image!(10, 10, [10]) == 5) |> all?(true)
false

# Float comparison (type coercion)
iex> (Image.build_image!(10, 10, [10]) == 10.0) |> all?(true)
true

# List comparison with bands
iex> img = Image.build_image!(1, 1, [10, 20]) == [10, 10]
iex> Image.to_list!(img)
[[[255, 0]]]

Reverse Comparison

# Float on the left side
iex> (10.0 == Image.build_image!(10, 10, [10])) |> all?(true)
true

# List on the left side
iex> ([10, 20, 30] == Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
true

Fallback Behavior

# Standard Kernel.== behavior when no images involved
iex> 4 == 4
true

a > b

@spec (Vix.Vips.Image.t() | number() | [number()]) >
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec term() > term() :: boolean()

Performs Greater_than (>) comparison between Images and numbers, returning the result as an Image.

Overview

The operator compares Images and numbers, with the result being an Image where:

  • 0 represents false
  • 255 represents true

When neither argument is an image, the operation delegates to Kernel.>/2.

Behavior

Image Comparison Rules

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Uses Operation.relational!(a, b, :VIPS_OPERATION_RELATIONAL_MORE). Bands are scaled up to match each other.

Type Handling

  • Images are cast to the smallest common format before comparison
  • Supports mixed numeric types (e.g., integers with floats)
  • Works bidirectionally (image < number and number < image)

Examples

Examples

Basic Image Comparison

# Comparing two images
iex> img = Image.build_image!(2, 2, [10, 15]) > Image.build_image!(2, 2, [5, 20])
iex> Image.shape(img)
{2, 2, 2}
iex> Image.to_list!(img)
[[[255, 0], [255, 0]], [[255, 0], [255, 0]]]

Checking All Pixels

# Using all?/2 to verify if all pixels match condition
iex> img = Image.build_image!(2, 2, [10]) > Image.build_image!(2, 2, [5])
iex> all?(img, true)
true

Multi-band Image Operations

# Equal values comparison
iex> (Image.build_image!(10, 10, [10, 20, 30]) > Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
false

# Multi-band vs single-band comparison
iex> (Image.build_image!(10, 10, [10]) > Image.build_image!(10, 10, [20, 30, 40])) |> all?(true)
false

# Comparing with smaller value
iex> (Image.build_image!(10, 10, [10, 20, 30]) > Image.build_image!(10, 10, [5])) |> all?(true)
true

Image vs. Number Comparison

# Single number compared to all bands
iex> img = Image.build_image!(1, 2, [5, 15, 25]) > 20
iex> Image.to_list!(img)
[[[0, 0, 255]], [[0, 0, 255]]]

# Comparing with integer
iex> (Image.build_image!(10, 10, [10]) > 20) |> all?(true)
false

# Comparing with float
iex> (Image.build_image!(10, 10, [20]) > 10.0) |> all?(true)
true

# List comparison with bands
iex> img = Image.build_image!(1, 1, [10, 20]) > [20, 10]
iex> Image.to_list!(img)
[[[0, 255]]]

Reverse Comparison

# Float on the left side
iex> (5.0 > Image.build_image!(10, 10, [4])) |> all?(true)
true

# List on the left side
iex> ([20, 30, 40] > Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
true

Fallback Behavior

# Standard Kernel.> behavior when no images involved
iex> 5 > 4
true

a >= b

@spec (Vix.Vips.Image.t() | number() | [number()]) >=
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec term() >= term() :: boolean()

Performs Greater_than_equal (>=) comparison between Images and numbers, returning the result as an Image.

Overview

The operator compares Images and numbers, with the result being an Image where:

  • 0 represents false
  • 255 represents true

When neither argument is an image, the operation delegates to Kernel.>=/2.

Behavior

Image Comparison Rules

  • Single number: Applied to all image bands
  • List matching image bands: Each number maps to corresponding band
  • List size does not match bands: Creates multi-band output with either the image bands or the list is scaled up to match the other.
  • Two images: Uses Operation.relational!(a, b, :VIPS_OPERATION_RELATIONAL_MOREEQ). Bands are scaled up to match each other.

Type Handling

  • Images are cast to the smallest common format before comparison
  • Supports mixed numeric types (e.g., integers with floats)
  • Works bidirectionally (image < number and number < image)

Examples

Examples

Basic Image Comparison

# Comparing two images
iex> img = Image.build_image!(2, 2, [10, 15]) >= Image.build_image!(2, 2, [5, 20])
iex> Image.shape(img)
{2, 2, 2}
iex> Image.to_list!(img)
[[[255, 0], [255, 0]], [[255, 0], [255, 0]]]

Checking All Pixels

# Using all?/2 to verify if all pixels match condition
iex> img = Image.build_image!(2, 2, [10]) >= Image.build_image!(2, 2, [5])
iex> all?(img, true)
true

Multi-band Image Operations

# Greater values comparison
iex> (Image.build_image!(10, 10, [20, 30, 40]) >= Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
true

# Equal values comparison
iex> (Image.build_image!(10, 10, [10, 20, 30]) >= Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
true

# Single vs multi-band comparison
iex> (Image.build_image!(10, 10, [20]) >= Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
false

# Multi vs single-band comparison
iex> (Image.build_image!(10, 10, [10, 20, 30]) >= Image.build_image!(10, 10, [10])) |> all?(true)
true

Image vs. Number Comparison

# Single number compared to all bands
iex> img = Image.build_image!(1, 2, [5, 10, 15]) >= 10
iex> Image.to_list!(img)
[[[0, 255, 255]], [[0, 255, 255]]]

# Comparing with larger number
iex> (Image.build_image!(10, 10, [10]) >= 20) |> all?(true)
false

# Comparing with float
iex> (Image.build_image!(10, 10, [20]) >= 10.0) |> all?(true)
true

# List comparison with bands
iex> img = Image.build_image!(1, 1, [10, 20]) >= [20, 10]
iex> Image.to_list!(img)
[[[0, 255]]]

Reverse Comparison

# Float on the left side
iex> (10.0 >= Image.build_image!(10, 10, [5])) |> all?(true)
true

# List on the left side
iex> ([20, 30, 40] >= Image.build_image!(10, 10, [10, 20, 30])) |> all?(true)
true

Fallback Behavior

# Standard Kernel.>= behavior when no images involved
iex> 5 >= 4
true

all?(image, bool)

@spec all?(Vix.Vips.Image.t(), boolean()) :: boolean()

Checks if all of the values are "true" (255) or "false" (0). Useful together with relational operators.

Examples

Check if two images are equal

iex> all?(Image.build_image!(10, 20, [255, 255, 255]), true)
true
iex> img = (Image.build_image!(10, 20, [50, 100, 150]) == Image.build_image!(10, 20, [50, 100, 150]))
iex> all?(img, true)
true
iex> img = (Image.build_image!(10, 20, [100, 150, 200]) < Image.build_image!(10, 20, [50, 100, 150]))
iex> all?(img, true)
false
iex> all?(img, false)
true

xor(a, b)

@spec xor(
  Vix.Vips.Image.t() | number() | [number()],
  Vix.Vips.Image.t() | number() | [number()]
) ::
  Vix.Vips.Image.t()
@spec xor(term(), term()) :: term()

Performs Bitwise Boolean XOR Operation (xor) between Images and numbers, returning the result as an Image.

Overview

The operation handles various input combinations:

  • Image xor Image
  • Image xor number(s)
  • number(s) xor Image

Input Handling

Values are cast up before operations. Float values are converted to integers

Number Inputs

  • Single number: Applied to all image bands uniformly
  • Number list:
    • If list size matches image bands: Each number applies to its respective band
    • If list size does not match the image bands: Either the image bands or the list is scaled up to match the other.

Image Inputs

  • When both inputs are images: Uses Operation.boolean!(a, b, :VIPS_OPERATION_BOOLEAN_EOR)

Examples

Image XOR Image Operations

iex> img = xor(Image.build_image!(2, 1, [0, 255, 0]), Image.build_image!(2, 1, [0, 255, 255]))
iex> Image.shape(img)
{2, 1, 3}
iex> Image.to_list!(img)
[[[0, 0, 255], [0, 0, 255]]]

# Identical Images
iex> xor(Image.build_image!(2, 2, [2, 4, 8]), Image.build_image!(2, 2, [2, 4, 8])) |> Image.to_list!()
[[[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]]]

# Different dimensions
iex> img = xor(Image.build_image!(1, 1, [2]), Image.build_image!(1, 2, [2, 4, 8]))
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[0, 6, 10]], [[2, 4, 8]]]

Image XOR Number Operations

# Single number comparison (applies to all bands)
iex> xor(Image.build_image!(1, 2, [2, 5, 3]), 6) |> Image.to_list!()
[[[4, 3, 5]], [[4, 3, 5]]]

# Float Comparison
iex> xor(Image.build_image!(1, 1, [10]), 6.0) |> Image.to_list!()
[[[12]]]

# List comparison (band-wise)
iex> xor(Image.build_image!(1, 1, [2, 2]), [1, 3]) |> Image.to_list!()
[[[3, 1]]]

Reverse Operations

# Number XOR Image
iex> xor(10.0, Image.build_image!(1, 1, [5])) |> Image.to_list!()
[[[15]]]

# List XOR Image
iex> xor([2, 2], Image.build_image!(1, 1, [1, 3])) |> Image.to_list!()
[[[3, 1]]]

a || b

@spec (Vix.Vips.Image.t() | number() | [number()]) ||
  (Vix.Vips.Image.t() | number() | [number()]) ::
  Vix.Vips.Image.t()
@spec term() || term() :: term()

Performs Bitwise Boolean OR Operation (||) between Images and numbers, returning the result as an Image.

Overview

The operation handles various input combinations:

  • Image || Image
  • Image || number(s)
  • number(s) || Image
  • non-Image values (falls back to Kernel)

Input Handling

Values are cast up before operations. Float values are converted to integers

Number Inputs

  • Single number: Applied to all image bands uniformly
  • Number list:
    • If list size matches image bands: Each number applies to its respective band
    • If list size does not match the image bands: Either the image bands or the list is scaled up to match the other.

Image Inputs

  • When both inputs are images: Uses Operation.boolean!(a, b, :VIPS_OPERATION_BOOLEAN_OR)

Examples

Image || Image Operations

iex> img = Image.build_image!(2, 1, [0, 255, 0]) || Image.build_image!(2, 1, [0, 255, 255])
iex> Image.shape(img)
{2, 1, 3}
iex> Image.to_list!(img)
[[[0, 255, 255], [0, 255, 255]]]

# Identical Images
iex> (Image.build_image!(2, 2, [2, 4, 8]) || Image.build_image!(2, 2, [2, 4, 8])) |> Image.to_list!()
[[[2, 4, 8], [2, 4, 8]], [[2, 4, 8], [2, 4, 8]]]

# Different dimensions
iex> img = Image.build_image!(1, 1, [2]) || Image.build_image!(1, 2, [2, 4, 8])
iex> Image.shape(img)
{1, 2, 3}
iex> Image.to_list!(img)
[[[2, 6, 10]], [[2, 4, 8]]]

Image || Number Operations

# Single number comparison (applies to all bands)
iex> (Image.build_image!(1, 2, [2, 4, 8]) || 4) |> Image.to_list!()
[[[6, 4, 12]], [[6, 4, 12]]]

# Float Comparison
iex> (Image.build_image!(1, 1, [4]) || 2.0) |> Image.to_list!()
[[[6]]]

# List comparison (band-wise)
iex> (Image.build_image!(1, 1, [2, 2]) || [1, 3]) |> Image.to_list!()
[[[3, 3]]]

Reverse Operations

# Number || Image
iex> (4.0 || Image.build_image!(1, 1, [2])) |> Image.to_list!()
[[[6]]]

# List || Image
iex> ([2, 2] || Image.build_image!(1, 1, [1, 3])) |> Image.to_list!()
[[[3, 3]]]

Kernel Fallback

# When neither argument is an image
iex> false || true
true