Skip to content

Commit

Permalink
Merge pull request #171 from akash-akya/accept-image-load-options
Browse files Browse the repository at this point in the history
Accept image loader options as keyword list
  • Loading branch information
akash-akya authored Oct 27, 2024
2 parents e67c5dd + f4888be commit 6b4f5bd
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 24 deletions.
58 changes: 35 additions & 23 deletions lib/vix/vips/image.ex
Original file line number Diff line number Diff line change
Expand Up @@ -313,38 +313,36 @@ defmodule Vix.Vips.Image do
JPEG, FITS, Matlab, OpenEXR, CSV, WebP, Radiance, RAW, PPM and
others.
Load options may be appended to filename as "[name=value,...]". For
example:
Optional param `opts` is passed to the image loader. Available
options depends on the file format. You can find all options
available for a format under operation function in
[Operation](./search.html?q=load+-buffer+-filename+-profile) module.
For example, you can find all of the options supported by
JPEG under `Vix.Vips.Operation.jpegload/2` function documentation.
```elixir
Image.new_from_file("fred.jpg[shrink=2]")
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:
```shell
$ vips jpegload
```
Opens "fred.jpg", downsampling by a factor of two.
at the command-line to see a summary of the available options for
the JPEG loader.
> #### Loading is fast {: .info}
> Only enough of the image is loaded to the memory to be able to
> fill out the header. Pixels will only be decompressed when they are
> needed.
If you want more control over the loader, Use specific format loader
If you want more control over the loader, Use the 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.
"""
@spec new_from_file(String.t()) :: {:ok, t()} | {:error, term()}
def new_from_file(path) do
path = Path.expand(path)

Nif.nif_image_new_from_file(normalize_string(path))
|> wrap_type()
@spec new_from_file(String.t(), keyword) :: {:ok, t()} | {:error, term()}
def new_from_file(path, opts \\ []) do
with {:ok, path} <- normalize_path(path),
{:ok, loader} <- Vix.Vips.Foreign.find_load(path),
{:ok, {ref, _optional}} <- Operation.Helper.operation_call(loader, [path], opts) do
{:ok, wrap_type(ref)}
end
end

@doc """
Expand Down Expand Up @@ -1331,4 +1329,18 @@ defmodule Vix.Vips.Image do
else
defp log_warn(msg), do: Logger.warn(msg)
end

@spec normalize_path(String.t()) :: {:ok, String.t()} | {:error, :invalid_path}
defp normalize_path(path) do
path =
path
|> Path.expand()
|> normalize_string()

if File.exists?(path) do
{:ok, path}
else
{:error, :invalid_path}
end
end
end
23 changes: 22 additions & 1 deletion test/vix/vips/image_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,33 @@ defmodule Vix.Vips.ImageTest do
end

test "new_from_file" do
assert {:error, "Failed to read image"} == Image.new_from_file("invalid.jpg")
assert {:error, :invalid_path} == Image.new_from_file("invalid.jpg")
assert {:error, "Failed to find load"} == Image.new_from_file(__ENV__.file)

assert {:ok, %Image{ref: ref}} = Image.new_from_file(img_path("puppies.jpg"))
assert is_reference(ref)
end

test "new_from_file supports optional arguments" do
assert {:ok, %Image{ref: ref} = img1} = Image.new_from_file(img_path("puppies.jpg"))
assert is_reference(ref)

assert {:ok, %Image{ref: ref} = img2} =
Image.new_from_file(img_path("puppies.jpg"), shrink: 2)

assert is_reference(ref)

assert Image.width(img1) == 2 * Image.width(img2)
end

test "new_from_file ignores invalid options" do
# png does not support `shrink` option
assert {:ok, %Image{ref: ref}} =
Image.new_from_file(img_path("gradient.png"), shrink: 2)

assert is_reference(ref)
end

test "new_from_buffer", %{dir: dir} do
assert {:error, "Failed to find load buffer"} == Image.new_from_buffer(<<>>)

Expand Down

0 comments on commit 6b4f5bd

Please sign in to comment.