Skip to content

Commit

Permalink
Accept write options as keyword list
Browse files Browse the repository at this point in the history
  • Loading branch information
akash-akya committed Jan 2, 2025
1 parent 45f3288 commit 5172698
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 48 deletions.
100 changes: 63 additions & 37 deletions lib/vix/vips/image.ex
Original file line number Diff line number Diff line change
Expand Up @@ -412,18 +412,6 @@ defmodule Vix.Vips.Image do
end
end

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

def new_from_file(path) do
path =
path
|> Path.expand()
|> normalize_string()

Nif.nif_image_new_from_file(path)
|> wrap_type()
end

@doc """
Opens `path` for reading, returns an instance of `t:Vix.Vips.Image.t/0`
Expand Down Expand Up @@ -454,6 +442,8 @@ defmodule Vix.Vips.Image do
from `Vix.Vips.Operation`. For example for jpeg use
`Vix.Vips.Operation.jpegload/2`
"""
@spec new_from_file(String.t(), keyword) :: {:ok, t()} | {:error, term()}

@doc since: "0.31.0"
def new_from_file(path, opts) do
with {:ok, path} <- normalize_path(path),
Expand All @@ -463,6 +453,14 @@ defmodule Vix.Vips.Image do
end
end

# TODO: deprecate accepting suffix options
def new_from_file(path) do
path = normalize_string(Path.expand(path))

Nif.nif_image_new_from_file(path)
|> wrap_type()
end

@doc """
Create a new image based on an existing image with each pixel set to `value`
Expand Down Expand Up @@ -778,56 +776,84 @@ defmodule Vix.Vips.Image do
end

@doc """
Write `vips_image` to a file.
Write `t:Vix.Vips.Image.t/0` to a file.
The image format is selected based on image extension in `path`.
A saver is selected based on image extension in `path`. You can
get list of supported extensions by `supported_saver_suffixes/0`.
Optional param `opts` is passed to the image saver. Available
options depends on the file format. You can find all options
available for a format under operation function in
[Operation](./search.html?q=save+-buffer+-filename+-profile) module.
Save options may be encoded in the filename. For example:
For example, you can find all of the options supported by JPEG saver
undre `Vix.Vips.Operation.jpegsave/3` function documentation.
```elixir
Image.write_to_file(vips_image, "fred.jpg[Q=90]")
# save with Quality set to 90
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`
"""
@spec write_to_file(t(), String.t()) :: :ok | {:error, term()}
@spec write_to_file(t(), String.t(), keyword) :: :ok | {:error, term()}

@doc since: "0.32.0"
def write_to_file(%Image{ref: _} = image, path, opts) do
path = normalize_string(Path.expand(path))

case Vix.Vips.Foreign.find_save(path) do
{:ok, saver} ->
Operation.Helper.operation_call(saver, [image, path], opts)

error ->
error
end
end

def write_to_file(%Image{ref: vips_image}, path) do
Nif.nif_image_write_to_file(vips_image, normalize_string(Path.expand(path)))
path = normalize_string(Path.expand(path))
Nif.nif_image_write_to_file(vips_image, path)
end

@doc """
Returns `vips_image` as binary based on the format specified by `suffix`.
Returns `t:Vix.Vips.Image.t/0` as a 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.
Optional param `opts` is passed to the image saver. Available
options depends on the file format. You can find all options
available for a format under operation function in
[Operation](./search.html?q=save+buffer+-filename+-profile) module.
Save options may be encoded in the filename. For example:
For example, you can find all of the options supported by JPEG saver
undre `Vix.Vips.Operation.jpegsave_buffer/2` function documentation.
```elixir
Image.write_to_buffer(vips_image, ".jpg[Q=90]")
# returns image in JPEG format as binary with Q factor set 90
Image.write_to_buffer(img, ".jpg", [Q: 90])
```
The full set of save options depend on the selected saver. You can
get list of available options for the saver
```shell
$ vips jpegsave
```
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_buffer/2`
"""
@spec write_to_buffer(t(), String.t()) ::
{:ok, binary()} | {:error, term()}
@spec write_to_buffer(t(), String.t(), keyword) :: {:ok, binary()} | {:error, term()}

@doc since: "0.32.0"
def write_to_buffer(%Image{ref: _} = image, suffix, opts) do
case Vix.Vips.Foreign.find_save_buffer(normalize_string(suffix)) do
{:ok, saver} ->
Operation.Helper.operation_call(saver, [image], opts)

error ->
error
end
end

def write_to_buffer(%Image{ref: vips_image}, suffix) do
Nif.nif_image_write_to_buffer(vips_image, normalize_string(suffix))
end
Expand Down
72 changes: 61 additions & 11 deletions test/vix/vips/image_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,45 @@ defmodule Vix.Vips.ImageTest do
assert File.read!(img_buf_out_path) == File.read!(img_file_out_path)
end

test "write_to_file", %{dir: dir} do
path = img_path("puppies.jpg")
describe "write_to_file" do
test "write_to_file", %{dir: dir} do
path = img_path("puppies.jpg")

{:ok, %Image{ref: ref} = im} = Image.new_from_file(path)
assert is_reference(ref)
{:ok, %Image{ref: ref} = im} = Image.new_from_file(path)
assert is_reference(ref)

out_path = Temp.path!(suffix: ".png", basedir: dir)
assert :ok == Image.write_to_file(im, out_path)
out_path = Temp.path!(suffix: ".png", basedir: dir)
assert :ok == Image.write_to_file(im, out_path)

stat = File.stat!(out_path)
assert stat.size > 0 and stat.type == :regular
stat = File.stat!(out_path)
assert stat.size > 0 and stat.type == :regular
end

test "write_to_file supports optional arguments", %{dir: dir} do
{:ok, img} = Image.new_from_file(img_path("puppies.jpg"))

out_path1 = Temp.path!(suffix: ".png", basedir: dir)
assert :ok = Image.write_to_file(img, out_path1, compression: 0)

out_path2 = Temp.path!(suffix: ".png", basedir: dir)
assert :ok = Image.write_to_file(img, out_path2, compression: 9)

# currently I only found this option to be verifiable easily!
assert File.stat!(out_path1).size > File.stat!(out_path2).size
end

test "write_to_file supports optional options suffix", %{dir: dir} do
{:ok, img} = Image.new_from_file(img_path("puppies.jpg"))

out_path1 = Temp.path!(suffix: ".png", basedir: dir)
assert :ok = Image.write_to_file(img, out_path1 <> "[compression=0]")

out_path2 = Temp.path!(suffix: ".png", basedir: dir)
assert :ok = Image.write_to_file(img, out_path2 <> "[compression=9]")

# currently I only found this option to be verifiable easily!
assert File.stat!(out_path1).size > File.stat!(out_path2).size
end
end

test "new_matrix_from_array", %{dir: _dir} do
Expand Down Expand Up @@ -232,9 +260,31 @@ defmodule Vix.Vips.ImageTest do
assert 2 == Image.n_pages(im)
end

test "write image to buffer", %{dir: _dir} do
{:ok, im} = Image.new_from_file(img_path("puppies.jpg"))
{:ok, _bin} = Image.write_to_buffer(im, ".jpg[Q=90]")
describe "write_to_buffer" do
test "write image to buffer", %{dir: _dir} do
{:ok, im} = Image.new_from_file(img_path("puppies.jpg"))
{:ok, _bin} = Image.write_to_buffer(im, ".jpg[Q=90]")
end

test "write_to_buffer supports optional arguments" do
{:ok, img} = Image.new_from_file(img_path("puppies.jpg"))

assert {:ok, bin1} = Image.write_to_buffer(img, ".png", compression: 0)
assert {:ok, bin2} = Image.write_to_buffer(img, ".png", compression: 9)

# currently I only found this option to be verifiable easily!
assert byte_size(bin1) > byte_size(bin2)
end

test "write_to_buffer supports optional options suffix" do
{:ok, img} = Image.new_from_file(img_path("puppies.jpg"))

assert {:ok, bin1} = Image.write_to_buffer(img, ".png[compression=0]")
assert {:ok, bin2} = Image.write_to_buffer(img, ".png[compression=9]")

# currently I only found this option to be verifiable easily!
assert byte_size(bin1) > byte_size(bin2)
end
end

test "new image from other image", %{dir: _dir} do
Expand Down

0 comments on commit 5172698

Please sign in to comment.