# `Vix.Vips.Image`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1)

Primary module for reading and writing image and image metadata.

This module allows you to read, write, manipulate and analyze images efficiently using the powerful
libvips image processing library. It offers operations like loading images, accessing metadata,
and extracting image bands.

## Basic Usage

    # Load an image from file
    {:ok, image} = Image.new_from_file("path/to/image.jpg")

    # Create a new RGB image
    {:ok, blank} = Image.build_image(width, height, [0, 0, 0])

## Access Syntax (Image Slicing)

The module implements Elixir's Access behavior, providing an intuitive way to slice and extract
image data across three dimensions: width, height, and bands (color channels).

### Band Extraction

Access individual color bands using integer indices:

    # Get the red channel from an RGB image
    red_channel = image[0]

    # Get the alpha channel (last band) from an RGBA image
    alpha = image[-1]

### Band Ranges

Extract multiple consecutive bands using ranges:

    # Get red and green channels from RGB
    red_green = image[0..1]

    # Get all channels.
    all_channels = image[0..-1//1]
    # Same as `all_channels = image`

### Dimensional Slicing

Slice images across multiple dimensions using lists of the form [width, height, bands]:

    # Get a 100x100 pixel square from the top-left corner
    top_left = image[[0..99, 0..99]]

    # Get the bottom-right 50x50 pixel square
    bottom_right = image[[-50..-1, -50..-1]]

    # Get the bottom-right 50x50 pixel square, and only green channel
    bottom_right = image[[-50..-1, -50..-1, 1]]

### Named Dimension Access

Use keyword lists for more explicit dimension specification:

    # Get first 200 pixels in width, maintaining full height and bands
    slice = image[[width: 0..199]]

    # Get specific height range with all bands
    middle = image[[height: 100..299]]

    # Extract specific band
    green = image[[band: 1]]

    # Get a 100x100 pixel square from the top-left corner, and only red-green channels
    bottom_right = image[[width: 0..99, height: 0..99, band: 0..1]]

See `Vix.Vips.Operation` for available image processing operations.

# `t`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L95)

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

Represents an instance of VipsImage

# `bands`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "bands" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-bands) for more details regarding `bands` function

# `build_image`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L408)

```elixir
@spec build_image(
  pos_integer(),
  pos_integer(),
  [number()],
  opts :: [
    interpretation: Vix.Vips.Operation.vips_interpretation() | :auto,
    format: Vix.Vips.Operation.vips_band_format() | :auto
  ]
) :: {:ok, t()} | {:error, term()}
```

Creates a new image with specified dimensions and background values.

Takes width, height, and a list of background values to create a new image. The background values
determine both the number of bands and initial pixel values.

## Parameters

  * `width` - Width of the image in pixels (positive integer)
  * `height` - Height of the image in pixels (positive integer)
  * `background` - List of numbers representing initial pixel values for each band. Defaults to [0, 0, 0]
  * `opts` - Keyword list of options

## Options

  * `:interpretation` - Color space interpretation. Can be a valid `vips_interpretation` or `:auto`.
     When `:auto`, determined by number of bands:
     * 1 band -> `:VIPS_INTERPRETATION_B_W`
     * 3 bands -> `:VIPS_INTERPRETATION_RGB`
     * 4 bands -> `:VIPS_INTERPRETATION_sRGB`
     * other -> `:VIPS_INTERPRETATION_MULTIBAND`

  * `:format` - Pixel value format. Can be a valid vips_format or `:auto`.
     When `:auto`, determined by value ranges. For example:
     * 0-255 -> `:VIPS_FORMAT_UCHAR`
     * decimal values -> `:VIPS_FORMAT_DOUBLE`
     * larger integers -> `:VIPS_FORMAT_INT`

## Examples

```elixir
iex> {:ok, %Image{ref: _} = img} = Image.build_image(1, 2, [10])
iex> Image.to_list(img)
{:ok, [[[10]], [[10]]]}
iex> Image.shape(img)
{1, 2, 1}
```

Sets the interpretation based on the bands

```elixir
iex> {:ok, img} = Image.build_image(1, 2, [10])
iex> Image.interpretation(img)
:VIPS_INTERPRETATION_B_W
iex> {:ok, img} = Image.build_image(10, 10, [10, 10, 10])
iex> Image.interpretation(img)
:VIPS_INTERPRETATION_RGB
iex> {:ok, img} = Image.build_image(10, 10, [10, 10, 10, 10])
iex> Image.interpretation(img)
:VIPS_INTERPRETATION_sRGB
iex> {:ok, img} = Image.build_image(10, 10, [10, 10, 10, 10], interpretation: :VIPS_INTERPRETATION_MULTIBAND)
iex> Image.interpretation(img)
:VIPS_INTERPRETATION_MULTIBAND
```

Sets the band format based on the values

```elixir
iex> {:ok, img} = Image.build_image(1, 2, [10, 9, 220])
iex> Image.format(img)
:VIPS_FORMAT_UCHAR
iex> {:ok, img} = Image.build_image(10, 10, [10, -120, 200])
iex> Image.format(img)
:VIPS_FORMAT_SHORT
iex> {:ok, img} = Image.build_image(10, 10, [10, -120, 1.0])
iex> Image.format(img)
:VIPS_FORMAT_DOUBLE
iex> {:ok, img} = Image.build_image(10, 10, [10, -40000, 39])
iex> Image.format(img)
:VIPS_FORMAT_INT
iex> {:ok, img} = Image.build_image(10, 10, [10, -80, 10], format: :VIPS_FORMAT_CHAR)
iex> Image.format(img)
:VIPS_FORMAT_CHAR
```

# `build_image!`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L440)

```elixir
@spec build_image!(pos_integer(), pos_integer(), [number()]) :: t() | no_return()
```

Creates a new image with specified dimensions and background values.

Similar to `build_image/4` but raises `Image.Error` on failure instead of returning error tuple.

## Examples

```elixir
iex> img = Image.build_image!(1, 2, [10])
iex> Image.to_list(img)
{:ok, [[[10]], [[10]]]}
iex> Image.shape(img)
{1, 2, 1}
```

See `build_image/4` for detailed documentation.

# `coding`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "coding" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-coding) for more details regarding `coding` function

# `copy_memory`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L921)

```elixir
@spec copy_memory(t()) :: {:ok, t()} | {:error, term()}
```

Copies an image to a memory buffer.

This function ensures that an image is fully loaded into memory, which is
required for certain operations like drawing or when you need to guarantee
the image is memory-resident for performance reasons.

If the image is already a memory buffer, it returns a reference to the
existing buffer. If the image is file-backed or represents a partial
computation, it allocates memory and copies the entire image to it.

## Parameters

* `image` - The source `t:Vix.Vips.Image.t/0` to copy to memory

## Returns

* `{:ok, image}` - A memory-resident copy of the image
* `{:error, reason}` - If the copy operation fails

## Examples

    iex> {:ok, image} = Image.new_from_file("test/images/puppies.jpg")
    iex> {:ok, _memory_image} = Image.copy_memory(image)
    iex> # _memory_image is now guaranteed to be in memory

## Use Cases

* Before performing draw operations that require memory-resident images
* When you need to ensure consistent performance for repeated operations
* Creating mutable copies for in-place modifications
* Optimizing memory access patterns for complex processing pipelines

# `fetch`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L167)

Extracts a band from an image using Access syntax.

This function implements the Access behaviour for images, enabling array-like
syntax for extracting bands and slices. See the module documentation for
detailed examples of Access syntax usage.

## Parameters

  * `image` - The source image
  * `band` - Integer index, Range, or list specifying what to extract

## Returns

  * `{:ok, image}` with extracted data
  * Raises ArgumentError for invalid access patterns

Access is read-only - `get_and_update/3` and `pop/2` are not supported.

## Examples

    # Get red channel
    {:ok, red} = Image.fetch(rgb_image, 0)

    # Get first two channels
    {:ok, rg} = Image.fetch(rgb_image, 0..1)

    # Get 100x100 region from top-left
    {:ok, region} = Image.fetch(image, [0..99, 0..99])

    # Get specific height range
    {:ok, slice} = Image.fetch(image, [height: 100..199])

See `Vix.Vips.Image` module docs for more details

# `filename`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "filename" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-filename) for more details regarding `filename` function

# `format`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

```elixir
@spec format(t()) :: Vix.Vips.Operation.vips_band_format() | no_return()
```

Get "format" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-format) for more details regarding `format` function

# `get_pixel`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1159)

```elixir
@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: `t: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 {: .warning}
> Loop through lot of pixels using `get_pixel` can be expensive.
> Use `extract_area` or Access syntax (slicing) instead

# `get_pixel!`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1177)

```elixir
@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.

# `has_alpha?`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1341)

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

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

Example

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

  has_alpha? = Image.has_alpha?(im)
```

# `header_field_names`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1357)

```elixir
@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

# `header_value`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1374)

```elixir
@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.

```elixir
{:ok, width} = Image.header_value(vips_image, "width")
```

# `header_value_as_string`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1394)

```elixir
@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

# `headers`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1462)

```elixir
@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,
  &quot;page-height&quot;: integer() | nil,
  &quot;n-pages&quot;: 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.

# `height`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "height" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-height) for more details regarding `height` function

# `interpretation`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "interpretation" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-interpretation) for more details regarding `interpretation` function

# `mode`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "mode" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-mode) for more details regarding `mode` function

# `mutate`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1309)

```elixir
@spec mutate(t(), (Vix.Vips.MutableImage.t() -&gt; 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

```elixir
  {: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)
```

# `n_pages`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

```elixir
@spec n_pages(t()) :: integer() | no_return()
```

Get "n-pages" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-n-pages) for more details regarding `n_pages` function

# `new_from_binary`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L654)

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

Creates a new image from raw pixel data with zero-copy performance.

This function wraps raw pixel data without copying, making it highly efficient for
integrating with other imaging libraries or processing pipelines. It's particularly
useful when working with raw pixel data from libraries like [`eVision`](https://github.com/cocoa-xu/evision) or
[`Nx`](https://github.com/elixir-nx/).

## Parameters

* `bin` - Binary containing raw pixel data in left-to-right, top-to-bottom order
* `width` - Image width in pixels
* `height` - Image height in pixels
* `bands` - Number of bands per pixel (e.g., 3 for RGB, 4 for RGBA)
* `band_format` - Format of each band (typically `:VIPS_FORMAT_UCHAR`)

## Endianness Requirements

The binary data MUST be in native endianness. When using bitstring syntax, always
specify the `native` modifier:

    # Correct - using native endianness
    <<r::native-integer-size(8), g::native-integer-size(8), b::native-integer-size(8)>>

    # Incorrect - default big endian
    <<r::integer-size(8), g::integer-size(8), b::integer-size(8)>>

See [Elixir docs](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#%3C%3C%3E%3E/1-endianness)
for more details.

## Examples

Creating an RGB image from raw pixel data

```elixir
pixels = <<
  255, 0, 0,    # Red pixel
  0, 255, 0,    # Green pixel
  0, 0, 255     # Blue pixel
>>
{:ok, image} = Image.new_from_binary(pixels, 3, 1, 3, :VIPS_FORMAT_UCHAR)
```

Working with grayscale data:

```elixir
gray_data = <<128, 64, 32, 16>>  # 4 gray pixels
{:ok, gray_image} = Image.new_from_binary(gray_data, 4, 1, 1, :VIPS_FORMAT_UCHAR)
```

Creating an RGB image from raw pixel data:

    pixel_data = get_rgb_pixels() # Binary of RGB values
    {:ok, image} = Image.new_from_binary(pixel_data, 640, 480, 3, :VIPS_FORMAT_UCHAR)

For loading formatted binary (JPEG, PNG, etc) see `new_from_buffer/2`.

# `new_from_buffer`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L581)

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

Creates a new image from formatted binary data (like JPEG, PNG, etc.).

This function attempts to automatically detect the image format from the binary data.
It's particularly useful when working with image data from network requests, databases,
or other binary sources.

## Parameters

* `bin` - Binary data containing a formatted image (JPEG, PNG, etc.)
* `opts` - Format-specific loading options (same as `new_from_file/2`)

## Examples

Basic usage with binary data:

    {:ok, image} = Image.new_from_buffer(jpeg_binary)

Loading with specific options:

    {:ok, image} = Image.new_from_buffer(jpeg_binary, shrink: 2)

Working with HTTP responses:

    {:ok, response} = HTTPClient.get("https://example.com/image.jpg")
    {:ok, image} = Image.new_from_buffer(response.body)

## Format-Specific Loading

For known formats, you can use specific loaders from `Vix.Vips.Operation`:

    {:ok, image} = Vix.Vips.Operation.jpegload_buffer(jpeg_binary, access: :VIPS_ACCESS_SEQUENTIAL)

# `new_from_enum`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L701)

```elixir
@spec new_from_enum(Enumerable.t(), String.t() | keyword()) ::
  {:ok, t()} | {:error, term()}
```

Creates a new image by lazily reading from an Enumerable source.

This function is ideal for processing large images without loading the entire file into memory.
It detects the image format from the initial bytes and reads remaining data on-demand.

## Parameters

* `enum` - An Enumerable producing image data (e.g., File.stream!, HTTP chunks)
* `opts` - Optional keyword list of format-specific options. To be backward compatible it also accepts options
as a string in "[name=value,...]" format for the time being.

## Examples

Reading from a file stream:

    {:ok, image} =
      File.stream!("large_photo.jpg", [], 65_536)
      |> Image.new_from_enum()

Reading from a file with options:

    {:ok, image} =
      File.stream!("large_photo.jpg", [], 65_536)
      |> Image.new_from_enum(shrink: 2)

Processing S3 stream:

    {:ok, image} =
      ExAws.S3.download_file("bucket", "image.jpg")
      |> Stream.map(&process_chunk/1)
      |> Image.new_from_enum()

## Format Options

To see format-specific options, check [Operation](./search.html?q=load+-buffer+-filename+-profile) module.

# `new_from_file`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L507)

# `new_from_file`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L497)
*since 0.31.0* 

```elixir
@spec new_from_file(
  String.t(),
  keyword()
) :: {:ok, t()} | {:error, term()}
```

Opens an image file for reading and returns a `t:Vix.Vips.Image.t/0` struct.

This function provides a high-level interface to load images from many format
depending on the libraries installed.

## Options

The `opts` parameter accepts format-specific loading options. Each format supports
different options which can be found in the [Operation](./search.html?q=load+-buffer+-filename+-profile)
module documentation.

## Examples

```elixir
# Basic usage:
{:ok, %Image{} = image} = Image.new_from_file("photo.jpg")

# Loading with options (downsampling by factor of 2):
{:ok, image} = Image.new_from_file("large_photo.jpg", shrink: 2)

# Loading a specific page from a multi-page TIFF
{:ok, page} = Image.new_from_file("document.tiff", page: 1)

# Loading a PNG with specific options:
{:ok, image} = Image.new_from_file("transparent.png", access: :VIPS_ACCESS_SEQUENTIAL)
```

To see all available options for a specific format, you can check the corresponding loader function. For example, `Vix.Vips.Operation.jpegload/2` documents all JPEG-specific options.

## Performance Notes

The loading process is optimized - only the image header is initially loaded into memory.
Pixel data is decompressed on-demand when accessed, making this operation memory-efficient
for large images.

## Advanced Usage

For more control over the loading process, consider using format-specific loaders from
`Vix.Vips.Operation`. For example:

```elixir
# Using specific JPEG loader
{:ok, image} = Vix.Vips.Operation.jpegload("photo.jpg", access: :VIPS_ACCESS_SEQUENTIAL)
```

# `new_from_image`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L540)

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

Creates a new image by cloning dimensions and properties from an existing image,
filling all bands with specified values.

The new image inherits the following properties from the source image:
* Width and height
* Format and color interpretation
* Resolution
* Offset

## Parameters

* `image` - Source image to clone properties from
* `value` - List of numbers representing values for each band

## Examples

Create a solid red image with same dimensions as source:

    {:ok, red_image} = Image.new_from_image(source_image, [255, 0, 0])

Create a semi-transparent overlay:

    {:ok, overlay} = Image.new_from_image(source_image, [0, 0, 0, 128])

# `new_from_list`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1274)

```elixir
@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.

```elixir
# 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

# `new_matrix_from_array`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1240)

```elixir
@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`.

```elixir
{: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

# `new_temp_file`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1220)

```elixir
@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.

```elixir
vips_image = Image.new_temp_file("%s.v")
```

# `offset`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

```elixir
@spec offset(t()) :: float() | no_return()
```

Get "offset" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-offset) for more details regarding `offset` function

# `orientation`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "orientation" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-orientation) for more details regarding `orientation` function

# `page_height`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "page-height" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-page-height) for more details regarding `page_height` function

# `scale`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "scale" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-scale) for more details regarding `scale` function

# `shape`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1502)

```elixir
@spec shape(t()) :: {pos_integer(), pos_integer(), pos_integer()}
```

Returns 3 element tuple representing `{width, height, number_of_bands}`

## Examples

```elixir
iex> img = Image.build_image!(100, 200, [1, 2, 3])
iex> Image.shape(img)
{100, 200, 3}
```

# `supported_saver_suffixes`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L877)

```elixir
@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.

# `to_list`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L841)

```elixir
@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 {: .warning}
> 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.

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

list = Vix.Vips.Image.to_list(histogram)
```

# `to_list!`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L859)

```elixir
@spec to_list!(t()) :: [[[number()]]] | no_return()
```

Same as `to_list!/1` but raises error instead of returning it.

# `width`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

```elixir
@spec width(t()) :: pos_integer() | no_return()
```

Get "width" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-width) for more details regarding `width` function

# `write_to_binary`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1131)

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

Extracts raw pixel data from a VIPS image as a binary term.

This is a lower-level alternative to `write_to_tensor/1` that returns only the
raw binary data without the associated metadata. It's primarily intended for
cases where you already know the image dimensions and format.

## Warning

It's recommended to use `write_to_tensor/1` instead of this function unless you
have a specific need for the raw binary data and already know:

* Image dimensions (height × width)
* Number of bands
* Pixel data format
* Data layout and organization

## Examples

Extracting raw binary data:

    {:ok, binary_data} = Image.write_to_binary(image)

# `write_to_buffer`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1037)

# `write_to_buffer`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1030)
*since 0.32.0* 

```elixir
@spec write_to_buffer(t(), String.t(), keyword()) ::
  {:ok, binary()} | {:error, term()}
```

Converts a VIPS image to a binary representation in the specified format.

This function is similar to `write_to_file/3` but returns the encoded image
as a binary instead of writing to a file. This is particularly useful for
web applications or when working with in-memory image processing pipelines.

## Parameters

* `image` - The source `t:Vix.Vips.Image.t/0` to convert
* `suffix` - Format extension (e.g., ".jpg", ".png")
* `opts` - Format-specific encoding options

## Examples

Basic conversion to different formats:

    # Convert to JPEG binary
    {:ok, jpeg_binary} = Image.write_to_buffer(image, ".jpg")

    # Convert to PNG binary
    {:ok, png_binary} = Image.write_to_buffer(image, ".png")

Converting with quality settings:

    # JPEG with 90% quality
    {:ok, jpeg_binary} = Image.write_to_buffer(image, ".jpg", Q: 90)

    # PNG with maximum compression
    {:ok, png_binary} = Image.write_to_buffer(image, ".png", compression: 9)

Web application example:

    def show_image(conn, %{"id" => id}) do
      image = MyApp.get_image!(id)
      {:ok, binary} = Image.write_to_buffer(image, ".jpg", Q: 85)

      conn
      |> put_resp_content_type("image/jpeg")
      |> send_resp(200, binary)
    end

# `write_to_file`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L979)

# `write_to_file`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L970)
*since 0.32.0* 

```elixir
@spec write_to_file(t(), String.t(), keyword()) :: :ok | {:error, term()}
```

Writes a VIPS image to a file in the format determined by the file extension.

## Parameters

* `image` - The source `t:Vix.Vips.Image.t/0` to save
* `path` - Destination file path (format determined by extension)
* `opts` - Format-specific saving options

## Format Options

Each format supports different saving options, which can be found in the
[Operation](./search.html?q=save+-buffer+-filename+-profile) module documentation.

## Examples

Basic usage:

    :ok = Image.write_to_file(image, "output.jpg")

Saving with quality settings:

    # JPEG with 90% quality
    :ok = Image.write_to_file(image, "output.jpg", Q: 90)

    # PNG with maximum compression
    :ok = Image.write_to_file(image, "output.png", compression: 9)

Saving with multiple options:

    # JPEG with quality and metadata stripping
    :ok = Image.write_to_file(image, "output.jpg", Q: 90, strip: true)

## Advanced Usage

For more control, use format-specific savers from `Vix.Vips.Operation`:

    # Using specific JPEG saver
    :ok = Vix.Vips.Operation.jpegsave(image, "output.jpg", Q: 95)

# `write_to_stream`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L812)

# `write_to_stream`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L787)
*since 0.32.0* 

```elixir
@spec write_to_stream(t(), String.t(), keyword()) :: Enumerable.t()
```

Creates a Stream that lazily writes image data in the specified format.

This function is particularly useful for handling large images or when streaming
directly to storage/network without intermediate files.

## Parameters

* `image` - The source image to stream
* `suffix` - Output format suffix. (e.g., ".jpg", ".png")
* `opts` - Optional keyword list of format-specific options (e.g., `[Q: 90]`)

## Examples

Basic streaming to file:

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

    :ok =
      Image.write_to_stream(image, ".png")
      |> Stream.into(File.stream!("output.png"))
      |> Stream.run()

Streaming with quality options:

    :ok =
      Image.write_to_stream(image, ".jpg", Q: 90, strip: true)
      |> Stream.into(File.stream!("output.jpg"))
      |> Stream.run()

Streaming to S3:

    :ok =
      Image.write_to_stream(image, ".png")
      |> Stream.each(&upload_chunk_to_s3/1)
      |> Stream.run()

## Format Options

Each format supports different saving options. View available options in
[Operation](./search.html?q=save+buffer+-filename+-profile) module.

# `write_to_tensor`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1093)

```elixir
@spec write_to_tensor(t()) :: {:ok, Vix.Tensor.t()} | {:error, term()}
```

Extracts raw pixel data from a VIPS image as a `Vix.Tensor` structure.

This function provides access to the underlying pixel data in a format suitable
for interoperability with other image processing or machine learning libraries.

## Image Structure

VIPS images are three-dimensional arrays with the following dimensions:
* Width: The horizontal size (up to 2^31 pixels)
* Height: The vertical size (up to 2^31 pixels)
* Bands: The number of channels per pixel (e.g., 3 for RGB, 4 for RGBA)

## Data Format

VIPS supports 10 different numeric formats for pixel values, ranging from
8-bit unsigned integers to 128-bit double complex numbers. Images are treated
as uninterpreted arrays of numbers - there's no inherent difference between
different color spaces with the same number of bands (e.g., RGBA vs CMYK).

## Performance Notes

Depending on the caching mechanism and image construction, VIPS may need to run all
the operations in the pipeline to produce the pixel data.

## Endianness Considerations

The binary data in the tensor uses native endianness. When processing this
data using bitstring syntax, always specify the `native` modifier:

    # Correct - using native endianness
    <<value::native-integer-size(8)>>

    # Incorrect - default big endian
    <<value::integer-size(8)>>

See [Elixir docs](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#%3C%3C%3E%3E/1-endianness) for more details.

## Examples

Converting an image to a tensor:

    {:ok, tensor} = Image.write_to_tensor(rgb_image)
    %Vix.Tensor{
      data: <<binary_data>>,
      shape: {height, width, 3},
      names: [:height, :width, :bands],
      type: :u8
    } = tensor

# `xoffset`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "xoffset" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-xoffset) for more details regarding `xoffset` function

# `xres`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "xres" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-xres) for more details regarding `xres` function

# `yoffset`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "yoffset" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-yoffset) for more details regarding `yoffset` function

# `yres`
[🔗](https://github.com/akash-akya/vix/blob/v0.38.0/lib/vix/vips/image.ex#L1428)

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

Get "yres" of the image

> #### More details {: .tip}
>
> See [libvips docs](https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-yres) for more details regarding `yres` function

---

*Consult [api-reference.md](api-reference.md) for complete listing*
